I have two constructs that I expected to be functionally the same, but they are not and I can't figure out why.
(define (x2 . b)
(display b)
(newline))
(x2 3 4 5) => (3 4 5)
((lambda (. b)
(display b)
(newline))
3 4 5) => Error: invalid use of `.'
In the R5RS, both definitions and lambdas accept . To make them behave identically I could construct the lambda like this:
((lambda b
(display b)
(newline))
3 4 5) => (3 4 5)
That is one of the valid constructs listed in report's definition of formal parameters. But if I attempt to use it with define, it results in an argument number mismatch error.
(define (x2 b)
(display b)
(newline))
(x2 3 4 5) => Error: bad argument count
I thought (define (x y) y)
was just syntactic sugar for (define x (lambda (y) y))
. It seems like that is true only in most cases. Can anyone explain the rationale for the different behavior?
These expressions represent an anonymous procedure with a fixed arity:
(define (x y) y)
(define (x y z) z)
And they're equivalent to:
(define x (lambda (y) y))
(define x (lambda (y z) z))
But take this procedure, with a variable number of arguments:
(define (x . y) y)
It's only equivalent to:
(define x (lambda y y))
Continuing with the examples, this procedure has a single mandatory parameter and the others are variable:
(define (x y . z) z)
And its equivalent form would be:
(define x (lambda (y . z) z))
So, the syntax is a bit different between the implicit/explicit use of a lambda
for defining procedures with a variable number of arguments, which is what the dot notation is used for in this case.
Also, syntax like '( . b)
is invalid, because in this case the dot notation is representing an improper list, that is, a list whose last element is not the empty list. On the other hand, this is valid: '(a . b)
. This explains why the expression (lambda ( . x) x)
is invalid; and given that (lambda (x) x)
represents an anonymous procedure with a single mandatory parameter, we're left with (lambda x x)
for representing an anonymous procedure with only a variable number of arguments and no mandatory arguments.
As far as I know the only rationale for why things are like this is by convention, and possibly because it's easier to parse.