简体   繁体   English

在Racket类函数中使用点表示法

[英]Using dot notation in Racket class functions

I have following class which works fine: 我的以下课程效果很好:

(define myob%
  (class object%
    (super-new)
    (init-field val)
    (define/public (getval) val)
    (define/public (setval v) (set! val v))   ))

(define ob1 (make-object myob% 5))

(send ob1 getval)
(send ob1 setval 10)
(send ob1 getval)

Output: 输出:

5
10

Following regex also works well: 以下正则表达式也可以很好地工作:

(define sl (regexp-match #px"^(.+)[.]([^.]+)$" "ob1.getval"))
sl

Output: 输出:

'("ob1.getval" "ob1" "getval")

I am trying to make a fn foo which should work like 'send' but take arguments in form of (foo ob1.getval) or (foo ob1.setval 10) . 我正在尝试制作一个fn foo,它应该像'send'一样工作,但是以(foo ob1.getval)(foo ob1.setval 10)形式接受参数。 Following macro is not working: 以下宏无法正常工作:

(define-syntax foo
    (syntax-rules ()
      ((_ sstr ...)
       (define sl (regexp-match #px"^(.+)[.]([^.]+)$"
                                (symbol->string sstr)))
       (send (string->symbol(list-ref sl 1))
             (string->symbol(list-ref sl 2))
             ...))))

(foo ob1.getval)

The error is: 错误是:

syntax-rules: bad syntax in: (syntax-rules () ((_ sstr ...) (define sl (regexp-match #px"^(.+)[.]([^.]+)$" (symbol->string sstr))) (send (list-ref sl 1) (list-ref sl 2) ...)))

Where is the error and how can this be corrected? 错误在哪里,如何纠正?

To use dot notation like this, you'll need to define a new #lang language, with its own reader. 要使用这样的点符号,您需要使用自己的阅读器定义一种新的#lang语言。 There are several tools to help with this, and I'll be using one of them, syntax/module-reader , to define #lang send-dot , which once defined can be used like this: 有几种工具可以帮助您解决此问题,我将使用其中一种syntax/module-reader来定义#lang send-dot ,一旦定义就可以像这样使用:

#lang send-dot

(define o
  (new (class object% (super-new)
         (define/public (f x) x))))

(o.f "hellooo")

In the latest snapshot version of Racket, you can use the read-cdot option. 最新版的Racket 快照中,您可以使用read-cdot选项。 Make sure you're on the latest snapshot version, since in 6.6, it's completely broken. 确保您使用的是最新的快照版本,因为在6.6中,它已完全损坏。

One way to define a #lang is by declaring a reader submodule. 定义#lang一种方法是声明一个reader子模块。 Make a directory called send-dot , and add a file called main.rkt . 创建一个名为send-dot的目录,并添加一个名为main.rkt的文件。 This file should provide everything from racket. 该文件应提供球拍的所有信息。

#lang racket

(provide (all-from-out racket))

This doesn't define a #lang yet. 这还没有定义#lang But to try it out, you can go to DrRacket's File menu, click on Package Manager, and in the Package Source field, enter the path to the send-dot directory. 但是要尝试一下,您可以转到DrRacket的“文件”菜单,单击“程序包管理器”,然后在“程序包源”字段中,输入send-dot目录的路径。 Once you do that, you should be able to use #lang s-exp send-dot in another file just like you would #lang racket . 完成此操作后,您应该可以像#lang racket一样在另一个文件中使用#lang s-exp send-dot

To define a reader for this language and make it a real #lang language, you can add a reader submodule that uses syntax/module-reader as its language. 要为该语言定义阅读器并使之成为真正的#lang语言,您可以添加使用syntax/module-reader作为其语言的readersyntax/module-reader

#lang racket

(provide (all-from-out racket))

;; This submodule defines the reader for the language
(module reader syntax/module-reader
  send-dot)

Now you should be able to use #lang send-dot just like #lang racket . 现在,您应该可以像#lang racket一样使用#lang send-dot了。

Now you need to do two more things. 现在您需要再做两件事。 One, turn on the read-cdot option so that (o.method args ...) is translated to ((#%dot o method) args ...) , and Two, define a #%dot macro so that ((#%dot o method) args ...) is equivalent to (send o method args ...) . 一是打开read-cdot选项,以便将(o.method args ...)转换为((#%dot o method) args ...) ,二是定义#%dot宏,以便((#%dot o method) args ...)等效于(send o method args ...)

For the first thing, you can use the #:wrapper1 option, using parameterize to turn read-cdot on. 首先,您可以使用#:wrapper1选项,并使用parameterize打开read-cdot

#lang racket

(provide (all-from-out racket))

;; This submodule defines the reader for the language
(module reader syntax/module-reader
  send-dot
  #:wrapper1 (lambda (thunk)
               ;; turns on the read-cdot option,
               ;; which will turn o.method into (#%dot o method),
               ;; and (o.method args ...) into ((#%dot o method) args ...)
               (parameterize ([read-cdot #true])
                 (thunk))))

For the second thing, you need to define a #%dot macro. 第二件事,您需要定义一个#%dot宏。 o.method , or (#%dot o method) , needs to be a function that calls the method, so you can use (lambda args (send/apply o method args)) . o.method(#%dot o method)需要是一个调用该方法的函数,因此可以使用(lambda args (send/apply o method args))

#lang racket

(provide #%dot (all-from-out racket))

;; transforms (#%dot o method) into a function that calls the method
;; so that ((#%dot o method) args ...) will be roughly equivalent to
;; (send o method args ...)
(define-syntax-rule (#%dot obj-expr method-id)
  (let ([obj obj-expr])
    (lambda args (send/apply obj method-id args))))

;; This submodule defines the reader for the language
(module reader syntax/module-reader
  send-dot
  #:wrapper1 (lambda (thunk)
               ;; turns on the read-cdot option,
               ;; which will turn o.method into (#%dot o method),
               ;; and (o.method args ...) into ((#%dot o method) args ...)
               (parameterize ([read-cdot #true])
                 (thunk))))

Now you should be able to use #lang send-dot like this: 现在您应该可以像下面这样使用#lang send-dot

#lang send-dot

(define o
  (new (class object% (super-new)
         (define/public (f x) x))))

(o.f "hellooo")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM