I'm learning Racket, and wrote this definition:
(define y 2)
(define (f (x y))
(print x)
(print y))
When I evaluate (f 1)
, x
is bound to 1
, and y
is bound to 2
. This seems very strange to me. How is this expression being expanded? What does the interpreter do with this?
The grammar for definitions in Racket is in the documentation.
3.14 Definitions: define, define-syntax, ...
(define id expr) (define (head args) body ...+) head = id | (head args) args = arg ... | arg ... . rest-id arg = arg-id | [arg-id default-expr] | keyword arg-id | keyword [arg-id default-expr]
Most of my Lisping is in Common Lisp where square brackets aren't parentheses, so I initially misread the grammar. The part about [arg-id default-expr]
means you can have an optional argument with a default value. So
(define (f (x y)) …)
defines f
as a procedure that accepts 0 or 1 arguments. If the argument is not provided, then its default value is y
. That's why this works when you have an earlier definition of y
. This also means that you can call (f)
, and you should see the value of y
printed:
This was pointed out to me on the Racket users mailing list by Robby Findler and Tony Garnock-Jones in the thread [racket] (define (f (x y)) body) when y has a previous definition.
This isn't legal in R5RS Scheme. The definition for definitions is given in:
5.2 Definitions
Definitions are valid in some, but not all, contexts where expressions are allowed. They are valid only at the top level of a and at the beginning of a .
A definition should have one of the following forms:
(define <variable> <expression>) (define (<variable> <formals>) <body>)
should be either a sequence of zero or more variables, or a sequence of one or more variables followed by a space-delimited period and another variable (as in a lambda expression). This form is equivalent to
(define <variable> (lambda (<formals>) <body>)). (define (<variable> . <formal>) <body>)
should be a single variable. This form is equivalent to
(define <variable> (lambda <formal> <body>)).
Dr.Racket won't accept your definition in the R5RS language:
In Racket an argument can be defined as (argument-name default-value)
(usually you'd use square brackets for this, but that's only a matter of style - the language itself does not care).
So (define (f (x y)) ...)
defines a function f
that takes one argument named x
whose default value is y
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With