rns*_*nso 2 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 getval)
Run Code Online (Sandbox Code Playgroud)
输出:
5
10
Run Code Online (Sandbox Code Playgroud)
以下正则表达式也可以很好地工作:
(define sl (regexp-match #px"^(.+)[.]([^.]+)$" "ob1.getval"))
sl
Run Code Online (Sandbox Code Playgroud)
输出:
'("ob1.getval" "ob1" "getval")
Run Code Online (Sandbox Code Playgroud)
我正在尝试制作一个fn foo,它应该像'send'一样工作,但采用(foo ob1.getval)or 形式的参数(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)
Run Code Online (Sandbox Code Playgroud)
错误是:
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) ...)))
Run Code Online (Sandbox Code Playgroud)
错误在哪里,如何纠正?
要使用这样的点符号,您需要#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")
Run Code Online (Sandbox Code Playgroud)
在最新版的Racket 快照中,您可以使用该read-cdot选项。确保您使用的是最新的快照版本,因为在6.6中,它已完全损坏。
定义a的一种方法#lang是声明一个reader子模块。创建一个名为的目录send-dot,并添加一个名为的文件main.rkt。该文件应提供球拍的所有信息。
#lang racket
(provide (all-from-out racket))
Run Code Online (Sandbox Code Playgroud)
这还没有定义#lang。但是要尝试一下,您可以转到DrRacket的“文件”菜单,单击“程序包管理器”,然后在“程序包源”字段中,输入send-dot目录的路径。完成后,您应该可以#lang s-exp send-dot像在一样在另一个文件中使用#lang racket。
要为该语言定义阅读器并使之成为一种实际#lang语言,可以添加一个用作其语言的reader子模块syntax/module-reader。
#lang racket
(provide (all-from-out racket))
;; This submodule defines the reader for the language
(module reader syntax/module-reader
send-dot)
Run Code Online (Sandbox Code Playgroud)
现在您应该可以#lang send-dot像一样使用#lang racket。
现在您需要再做两件事。一,打开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))))
Run Code Online (Sandbox Code Playgroud)
第二件事,您需要定义一个#%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))))
Run Code Online (Sandbox Code Playgroud)
现在您应该可以这样使用#lang send-dot:
#lang send-dot
(define o
(new (class object% (super-new)
(define/public (f x) x))))
(o.f "hellooo")
Run Code Online (Sandbox Code Playgroud)