Macros 在Racket类函数中使用点表示法
我有以下课程,效果很好:Macros 在Racket类函数中使用点表示法,macros,scheme,racket,Macros,Scheme,Racket,我有以下课程,效果很好: (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 g
(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
'("ob1.getval" "ob1" "getval")
以下正则表达式也很有效:
(define sl (regexp-match #px"^(.+)[.]([^.]+)$" "ob1.getval"))
sl
输出:
5
10
'("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) ...)))
错误在哪里?如何更正?要使用这样的点表示法,您需要定义一种新的
#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")
#lang send-dot
(define o
(new (class object% (super-new)
(define/public (f x) x))))
(o.f "hellooo")
在球拍中,您可以使用该选项。确保您使用的是最新的快照版本,因为在6.6中,它已完全损坏
定义#lang
的一种方法是声明读取器
子模块。创建一个名为send dot
的目录,并添加一个名为main.rkt
的文件。这个文件应该提供一切从球拍
#lang racket
(provide (all-from-out racket))
这还没有定义一个#lang
。但要试用它,您可以进入DrRacket的文件菜单,单击Package Manager,然后在Package Source字段中输入send dot
目录的路径。一旦你这样做了,你应该能够在另一个文件中使用#lang s-exp send dot
,就像你使用#lang racket
一样
要定义此语言的读取器并使其成为真正的#lang
语言,可以添加使用语法/模块读取器
作为其语言的读取器
子模块
#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
现在你还需要做两件事。第一,打开选项,以便将(o.method args…
转换为((#%dot o method)args…
),第二,定义#%dot
宏,以便(#%dot o method)args…
等同于(send o method args…
)
首先,您可以使用#:wrapper1
选项,使用参数化
来启用
对于第二件事,您需要定义一个#%dot
宏o.method
或(#%dot o method)
需要是调用该方法的函数,因此可以使用(lambda args(send/apply o method args))
现在您应该能够像这样使用#lang send dot
:
#lang send-dot
(define o
(new (class object% (super-new)
(define/public (f x) x))))
(o.f "hellooo")
#lang send-dot
(define o
(new (class object% (super-new)
(define/public (f x) x))))
(o.f "hellooo")
另外,
sstr
表示语法对象,而不是符号,需要使用syntax->datum
进行转换。(与发送
相反的问题)你能用正确的代码作为答案吗?不幸的是,修复这些问题是不够的,我不确定正确的代码是什么。太好了。在这里,您可以简单地补充一下,在这种新语言中,dot如何也可以用于结构元素(参考)对象更容易,因为它们可以依赖于动态分派。如果您想mydog.name
,结构会更难一些,但是如果您想mydog.dog name
被翻译成(dog name mydog)
将mydog.dog-name转换成(dog name mydog)的代码会更容易一些。或者只是因为read cdot在这里是活动的,所以它才起作用。我相信它将不得不在没有括号的情况下使用。是这样吗?