Extensible macro definitions

↘锁芯ラ 提交于 2019-12-04 03:26:48

In Racket, you can do this with modules. You could create a module that re-exports the entire Racket language except for Racket's lambda, and exports your new macro under the name lambda. I'll show one way to arrange the code.

The foo-lambda module defines and exports the foo-lambda form, which creates procedures that print "foo\n" when applied.

(module foo-lambda racket
  (define-syntax-rule (foo-lambda formals body ...)
    (lambda formals (displayln "foo") body ...))
  (provide foo-lambda))

The racket-with-foo-lambda module re-exports the entire Racket language except it provides foo-lambda under the name lambda.

(module racket-with-foo-lambda racket
  (require 'foo-lambda)
  (provide (except-out (all-from-out racket) lambda)
           (rename-out [foo-lambda lambda])))

Now you can write a module in this "new language":

(module some-program 'racket-with-foo-lambda
  (define f (lambda (x) x))
  (f 2))
(require 'some-program)

Note that this doesn't change the Racket version of lambda, and other Racket forms still use the Racket lambda binding. For example, if you rewrote the definition of f above as (define (f x) x), then Racket's define would expand into a use of Racket's lambda, and you would not get the "foo" printout.

You can chain extensions: each extension is defined in a module that imports the previous version. For example, your bar-lambda module would import the foo-lambda module, and so on.

Racket does this internally, in fact. The compiler only understands lambda with positional arguments, but the Racket language has a lambda that supports both positional and keyword arguments. The implementation of the Racket language has a module that replaces the built-in lambda and #%app (implicitly used to handle function application syntax) with versions that handle keyword arguments.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!