David542
David542

Reputation: 110502

Scheme allow uppercase define

To define a square in scheme I can do the following:

(define (square x) (* x x)

However, if I use a capital DEFINE, I get an invalid identifier:

(DEFINE (square x) (* x x)

Is there a way to do something like the following?

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

Upvotes: 1

Views: 84

Answers (1)

ad absurdum
ad absurdum

Reputation: 21360

You need to use a macro to create syntax that uses the define syntax, and the macro needs to be able to take arguments in all of the ways that define can.

For R6RS Scheme, R6RS says:

(define <variable> <expression>)‌‌           syntax 
(define <variable>)‌‌                        syntax 
(define (<variable> <formals>) <body>)‌‌     syntax 
(define (<variable> . <formal>) <body>)‌‌    syntax

Since the R6RS Scheme define syntax requires at least one argument, this macro requires at least one argument, and it will allow all of the above uses. Note that the pattern (_ e1 e2 ...) matches _ with DEFINE, and then one or more expressions:

(define-syntax DEFINE
  (syntax-rules ()
    ((_ e1 e2 ...)
     (define e1 e2 ...))))

Racket's define syntax requires at least two arguments, and this is also true of define in R5RS and R7RS Scheme. The sicp language follows R5RS, so the define in #lang sicp should also require two arguments. Racket has a convenient define-syntax-rule form that is more concise than define-syntax, though either would work here. Note that the pattern (DEFINE e1 e2 e3 ...) matches DEFINE and then two or more expressions:

#lang racket

(define-syntax-rule (DEFINE e1 e2 e3 ...) (define e1 e2 e3 ...))

But, the sicp language does not have define-syntax-rule, so we will have to settle for define-syntax, with pattern matching as in R5RS:

#lang sicp

(define-syntax DEFINE
  (syntax-rules ()
    ((_ e1 e2 e3 ...)
     (define e1 e2 e3 ...))))

Some example uses of the final #lang sicp definition:

> (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)

The first of these two would be legal in R6RS Scheme, but not in R5RS or R7RS Scheme, #lang racket, or #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}

Upvotes: 3

Related Questions