方案允许大写定义

Scheme allow uppercase define

要在方案中定义 square,我可以执行以下操作:

(define (square x) (* x x)

但是,如果我使用大写 DEFINE,我会得到一个无效的标识符:

(DEFINE (square x) (* x x)

有没有办法做类似下面的事情?

#lang sicp
; using DrRacket
(define (DEFINE) define) ; sort of a macro where DEFINE expands to define

您需要使用宏来创建使用 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 Scheme 中的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}