8

My friend shows this to me, and I am really curious why it works like this. I at first thought that it's gonna be a syntax error, but it doesn't... Here're some of my experiments:

> (lambda lambda lambda)
#<procedure>
> ((lambda lambda lambda))
'()
> ((lambda lambda lambda) 1 2 3 4 5 6 7)
'(1 2 3 4 5 6 7)
> (lambda lambda foo)
#<procedure>
> ((lambda lambda foo))
foo: undefined;
 cannot reference an identifier before its definition
> (lambda lambda 1 2 3 4 5)
#<procedure>
> ((lambda lambda 1 2 3 4 5))
5
> (lambda foo lambda)
. lambda: bad syntax in: lambda
> (lambda 1 2 3)
. lambda: bad argument sequence in: 1
> ((lambda) 1 2 3)
. lambda: bad syntax in: (lambda)

So it seems:

  1. In lambda, lambda could be arg-ids?
  2. In lambda, lambda could be a list constructor?
Sorawee Porncharoenwase
  • 6,305
  • 1
  • 14
  • 28

1 Answers1

8

Ohhh I got it. lambda could be shadowed!

> ((lambda (lambda) (+ 1 lambda)) 7)
8

Also, the syntax given at https://docs.racket-lang.org/guide/lambda.html is not entirely correct because at arg-ids position, an identifier could be there! This will bind the list of arguments with the identifier:

> ((lambda foo foo) 1 2 3 4)
'(1 2 3 4)

These explain it!

Sorawee Porncharoenwase
  • 6,305
  • 1
  • 14
  • 28
  • Thx :) In fact, the link I posted mentioned `rest-id` as well in 4.4.1, but I didn't see it! – Sorawee Porncharoenwase Feb 16 '16 at 07:48
  • 2
    Yes. However, there is one more strange case that this doesn't explain. `(lambda lambda foo)` = `#`. And that's because this is in a REPL, where you can do `(define (f x) foo)` and then define foo later, so that for instance mutual recursion works. But for these things, you really should put them in a file, because that's what will show their true behavior. In a file by itself, `(lambda lambda foo)` will be an error, as it should. – Alex Knauth Feb 16 '16 at 14:41