2

I have two constructs that I expected to be functionally the same, but they are not and I can't figure out why.

Using define

(define (x2 . b)
  (display b)
  (newline))

(x2 3 4 5) => (3 4 5)

Using lambda

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

AndrewE
  • 353
  • 1
  • 4
  • 16

2 Answers2

2

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.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
2

(. arguments) is invalid syntax. The dot indicates the separation between two parts of a pair and you have no first part here. I do see that you actually mean arguments here and that it should not be a list at all.

The define that looks like this:

(define (name . arguments)
  ..)

Are the same as:

(define name 
  (lambda arguments
    ..))

An example with one argument:

(define (name arg1 . arguments)
  ..)

Becomes

(define name 
  (lambda (arg1 . arguments)
    ..))

The reason is simple: (cdr '(name . arguments)) ; ==> arguments and (cdr '(name arg1 . arguments)) ; ==> '(arg1 . arguments).

Alexis King
  • 43,109
  • 15
  • 131
  • 205
Sylwester
  • 47,942
  • 4
  • 47
  • 79