是否有重新定义“定义"的有效用例?在计划/球拍中? [英] Is there a valid usecase for redefining "define" in scheme/racket?

查看:36
本文介绍了是否有重新定义“定义"的有效用例?在计划/球拍中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩球拍/方案,它允许我重新定义例如 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆