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在这里是活动的,所以它才起作用。我相信它将不得不在没有括号的情况下使用。是这样吗?