[英]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
作为其语言的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)
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.