是否有重新定义“定义"的有效用例?在计划/球拍中? [英] Is there a valid usecase for redefining "define" in scheme/racket?
问题描述
我正在玩球拍/方案,它允许我重新定义例如 define
并将其绑定为一个值.
I'm playing around with racket/scheme and it allows me to redefine for instance define
and bind it as a value.
> (define define 2)
> define
2
在那个范围内,我不能再使用 define
定义任何东西,因为它显然绑定到 2.这适用于我用 (if
,cond
等).
In that scope I can no longer define anything using define
since it is obviously bound to 2. This works for all "keywords" I tried it with (if
, cond
etc.).
但是不能使用define
来指定我自己的定义函数:
However it is not possible to use define
to specify my own definition function:
> (define mydef define)
stdin::14: define: not allowed in an expression context in: define
=== context ===
/usr/share/racket/collects/racket/private/norm-define.rkt:8:4: normalize-definition
/usr/share/racket/collects/racket/private/kw.rkt:796:2
/usr/share/racket/collects/racket/private/misc.rkt:87:7
我想有另一种方法可以扩展球拍中的语言以添加我自己的定义函数,但为什么不允许这种方式?
I suppose there is another means of extending the language in racket to add my own definition function should I want to, but why is this way disallowed?
这确实让我想知道是否有任何有效的用例来重新定义 define
?我意识到这有点基于意见,但我正在寻找这样的用例可能这样做是合理的(无论是否是另一回事).
This does leave me wondering if there is any valid use case at all for redefining define
? I realize that this is a bit opinion based, but I'm looking for use cases where this might be a justified thing to do (whether it is or not, is another matter).
推荐答案
是的,您可能实际上想要扩展 define
表单以提供标准 define
没有的功能'不.一个例子是提供装饰器(感谢 uselpa 对灵感的回答):
Yes, you might actually want to extend the define
form to provide capabilities that the standard define
doesn't. An example is providing decorators (thanks to uselpa's answer for inspiration):
(require (only-in racket/base (define basic-define)))
(define-syntax wrap-decorators
(syntax-rules ()
((_ () value)
value)
((_ (decorator next ...) value)
(decorator (wrap-decorators (next ...) value)))))
(define-syntax define
(syntax-rules (@)
((_ (@ decorator ...) (id . params) body ...)
(define (@ decorator ...) id (lambda params body ...)))
((_ (@ decorator ...) id value)
(define id (wrap-decorators (decorator ...) value)))
((_ other ...)
(basic-define other ...))))
(define (trace label)
(lambda (f)
(lambda args
(dynamic-wind (thunk (eprintf "enter ~a: ~s~%" label args))
(thunk (apply f args))
(thunk (eprintf "exit ~a: ~s~%" label args))))))
现在你可以这样使用它:
Now you can use it this way:
(define (@ (trace 'hypot)) (hypot x y)
(sqrt (+ (sqr x) (sqr y))))
这会导致 hypot
函数被 trace
包裹,所以当你调用它时,会发生跟踪:
This causes the hypot
function to be wrapped with trace
so when you call it, tracing happens:
> (hypot 3 4)
enter hypot: (3 4)
exit hypot: (3 4)
5
或者,使用uselpa的memoize
函数,可以使用:
Or, using uselpa's memoize
function, you can use:
(define (@ memoize) (fib n)
(if (< n 2)
n
(+ (fib (sub1 n)) (fib (- n 2)))))
并获得快速记忆的 fib
函数.您甚至可以跟踪和记忆它,只显示实际(缓存未命中)调用:
and get a speedy memoised fib
function. You can even trace and memoise it, showing only the actual (cache miss) invocations:
(define (@ (trace 'fib) memoize) (fib n)
(if (< n 2)
n
(+ (fib (sub1 n)) (fib (- n 2)))))
请注意,在我的宏中,我将 Racket 的 define
导入为 basic-define
,以便我重新定义的 define
可以委托给它.
Notice, in my macro, that I imported Racket's define
as basic-define
, so that my redefined define
could delegate to it.
这篇关于是否有重新定义“定义"的有效用例?在计划/球拍中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!