我有以下类,它工作得很好:
(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)输出:
5
10下面的正则表达式也可以很好地工作:
(define sl (regexp-match #px"^(.+)[.]([^.]+)$" "ob1.getval"))
sl输出:
'("ob1.getval" "ob1" "getval")我正在尝试做一个fn foo,它应该像'send‘一样工作,但以(foo ob1.getval)或(foo ob1.setval 10)的形式接受参数。以下宏不起作用:
(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)错误是:
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) ...)))错误在哪里?如何纠正这个错误?
发布于 2016-08-30 22:17:01
要使用这样的点表示法,您需要定义一种新的#lang语言,该语言具有自己的阅读器。有几个工具可以帮助实现这一点,我将使用其中一个工具syntax/module-reader来定义#lang send-dot,一旦定义,它就可以像这样使用:
#lang send-dot
(define o
(new (class object% (super-new)
(define/public (f x) x))))
(o.f "hellooo")在球拍的latest snapshot version中,可以使用read-cdot选项。请确保您使用的是最新的快照版本,因为在6.6中,它完全崩溃了。
定义#lang的一种方法是声明一个reader子模块。创建一个名为send-dot的目录,并添加一个名为main.rkt的文件。这个文件应该提供球拍中的所有内容。
#lang racket
(provide (all-from-out racket))这还没有定义#lang。但要尝试它,您可以转到DrRacket的文件菜单,单击包管理器,并在包源字段中输入send-dot目录的路径。一旦你这样做了,你应该能够在另一个文件中使用#lang s-exp send-dot,就像使用#lang racket一样。
要定义该语言的阅读器并使其成为真正的#lang语言,可以添加一个使用syntax/module-reader作为其语言的reader子模块。
#lang racket
(provide (all-from-out racket))
;; This submodule defines the reader for the language
(module reader syntax/module-reader
send-dot)现在您应该能够像使用#lang racket一样使用#lang send-dot了。
现在,您还需要做两件事。首先,启用read-cdot选项,以便将(o.method args ...)转换为((#%dot o method) args ...);其次,定义#%dot宏,使((#%dot o method) args ...)等效于(send o method args ...)。
首先,您可以使用#: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))))对于第二件事,您需要定义一个#%dot宏。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))))现在,您应该能够像这样使用#lang send-dot:
#lang send-dot
(define o
(new (class object% (super-new)
(define/public (f x) x))))
(o.f "hellooo")https://stackoverflow.com/questions/39224842
复制相似问题