是否有一个有效的用例来重新定义scheme/racket中的"define"?

Emi*_*l H 4 scheme language-features racket

我正在玩球拍/方案,它允许我重新定义例如define并将其绑定为值.

> (define define 2)
> define
2
Run Code Online (Sandbox Code Playgroud)

在该范围内,我可以使用不再定义什么define,因为它显然是必然2.这适用于所有的"关键字"我想它(if,cond等等).

但是,无法使用define指定我自己的定义函数:

> (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
Run Code Online (Sandbox Code Playgroud)

我想还有另一种方法可以在球拍中扩展语言,以便在我想要的时候添加我自己的定义功能,但为什么这种方式不被允许?

这确实让我想知道是否有任何有效的用例重新定义define?我意识到这有点基于意见,但我正在寻找可能是合理的事情的用例(无论是否是另一回事).

Chr*_*ung 5

是的,您实际上可能希望扩展define表单以提供标准所define不具备的功能.一个例子是提供装饰器(感谢uselpa的灵感答案):

(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))))))
Run Code Online (Sandbox Code Playgroud)

现在你可以这样使用它:

(define (@ (trace 'hypot)) (hypot x y)
  (sqrt (+ (sqr x) (sqr y))))
Run Code Online (Sandbox Code Playgroud)

这会导致hypot函数被包装,trace因此当您调用它时,会发生跟踪:

> (hypot 3 4)
enter hypot: (3 4)
exit hypot: (3 4)
5
Run Code Online (Sandbox Code Playgroud)

或者,使用uselpa的memoize功能,您可以使用:

(define (@ memoize) (fib n)
  (if (< n 2)
      n
      (+ (fib (sub1 n)) (fib (- n 2)))))
Run Code Online (Sandbox Code Playgroud)

并获得快速的记忆fib功能.您甚至可以跟踪和记忆它,仅显示实际(缓存未命中)调用:

(define (@ (trace 'fib) memoize) (fib n)
  (if (< n 2)
      n
      (+ (fib (sub1 n)) (fib (- n 2)))))
Run Code Online (Sandbox Code Playgroud)

请注意,在我的宏,我进口球拍的define作为basic-define,让我重新定义了define可委托给它.