您需要使用宏来创建使用define 语法的语法,并且该宏需要能够以define 可以采用的所有方式接受参数。
对于 R6RS 方案,R6RS says:
(define <variable> <expression>) syntax
(define <variable>) syntax
(define (<variable> <formals>) <body>) syntax
(define (<variable> . <formal>) <body>) syntax
由于 R6RS Scheme define 语法至少需要一个参数,因此该宏至少需要一个参数,并且它允许上述所有用途。请注意,(_ e1 e2 ...) 模式匹配 _ 和 DEFINE,然后是 一个 或多个表达式:
(define-syntax DEFINE
(syntax-rules ()
((_ e1 e2 ...)
(define e1 e2 ...))))
Racket 的define 语法至少需要两个 参数,R5RS 和R7RS 方案中的define 也是如此。 sicp 语言遵循 R5RS,因此 #lang sicp 中的 define 也应该需要两个参数。 Racket 有一个方便的define-syntax-rule 形式,它比define-syntax 更简洁,尽管两者都可以在这里工作。请注意,模式 (DEFINE e1 e2 e3 ...) 匹配 DEFINE 然后是 两个 或更多表达式:
#lang racket
(define-syntax-rule (DEFINE e1 e2 e3 ...) (define e1 e2 e3 ...))
但是,sicp 语言没有 define-syntax-rule,所以我们将不得不满足于 define-syntax,使用 R5RS 中的模式匹配:
#lang sicp
(define-syntax DEFINE
(syntax-rules ()
((_ e1 e2 e3 ...)
(define e1 e2 e3 ...))))
最终#lang sicp 定义的一些示例用法:
> (DEFINE x 42)
> x
42
> (DEFINE (my-add x y) (+ x y))
> (my-add 1 2)
3
> (DEFINE (my-list . xs) xs)
> (my-list 1 2 3)
(1 2 3)
> (DEFINE (my-args a b . c) (cons (list a b) c))
> (my-args 1 2 3 4 5)
((1 2) 3 4 5)
这两个中的第一个在 R6RS 方案中是合法的,但在 R5RS 或 R7RS 方案中不合法,#lang racket 或 #lang sicp:
> (DEFINE x)
; define-uppercase.rkt:56:0: DEFINE: bad syntax
; in: {DEFINE x}
> (DEFINE)
; define-uppercase.rkt:57:0: DEFINE: bad syntax
; in: {DEFINE}