1

I recently got in possession of a copy of "Essentials of Programming Languages", second edition. At page 29, the book introduces the following Scheme-flavored grammar for lambda calculus:

<expression> ::= <identifier>
             ::= (lambda (<identifier>) <expression>)
             ::= (<expression> <expression>)

It then proceeds to introduce a definition (Definition 1.3.3, page 31) for free and bound variables, which reads:

A variable x occurs free in a lambda calculus expression E if and only if

1. E is a variable reference and E is the same as x; or
2. E is of the form (lambda (y) E'), where y is different from x and x occurs free in E'; or
3. E is of the form (E1 E2) and x occurs free in E1 or E2.

A variable x occurs bound in a lambda calculus expression E if and only if

1. E is of the form (lambda (y) E'), where x occurs bound in E' or x and y are the same variable and y occurs free in E'; or
2. E is of the form (E1 E2) and x occurs bound in E1 or E2.

Such a definition is then readily transformed in two Scheme procedures, named, resp., occurs-free? and occurs-bound?:

(define occurs-free?
  (lambda (var exp)
    (cond
      ((symbol? exp) (eqv? exp var))
      ((eqv? (car exp) 'lambda)
       (and (not (eqv? (caadr exp) var))
            (occurs-free? var (caddr exp))))
      (else (or (occurs-free? var (car exp))
                (occurs-free? var (cadr exp)))))))

(define occurs-bound?
  (lambda (var exp)
    (cond
      ((symbol? exp) #f)
      ((eqv? (car exp) 'lambda)
       (or (occurs-bound? var (caddr exp))
           (and (eqv? (caadr exp) var)
                (occurs-free? var (caddr exp)))))
      (else (or (occurs-bound? var (car exp))
                (occurs-bound? var (cadr exp)))))))

One would expect occurs-bound? to return #t when combinators (i.e., procedures only consisting of bound variables) are fed as input. However, the test fails for the K combinator:

> (occurs-bound? 'x '(lambda (c) (lambda (x) c)))
#f

This is because point 1. in the definition of bound variables, which states that for a variable to be bound it must be both quantified in a lambda and later appear free in its body. Sincex is ignored in the body of the inner lambda, the test returns false.

Apparently, occurs-bound? is not presented in the third edition, so it is not possible to make any comparison with the most recent edition of the book.

Is the above definition flawed, or am I missing something? Here's a repl for the code.

Thank you

Ilio Catallo
  • 3,152
  • 2
  • 22
  • 40
  • Note that in the definition, the names "x" and "y" are not variables but meta-variables; they range over lambda-variables. Hence the phrasing "x and y are *the same variable* and y occurs free in E'" (emphasis mine). – molbdnilo Nov 01 '18 at 08:48
  • Good point. "Types and Programming Languages" is more precise in this regard. – Ilio Catallo Nov 01 '18 at 11:24

1 Answers1

1

Why should it be flawed? What's the origin for your suspicions?

Does 'x occur bound in '(lambda (c) (lambda (y) c))?

Does 'x occur bound in '(lambda (c) (lambda (z) c))?

Does it seem strange to you that it doesn't? I would expect not. Why then should it be considered occurring bound in the alpha-equivalent '(lambda (c) (lambda (x) c)), then?

It shouldn't. It's not even there.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • Thank your for your answer. Admittely, I am not proficient in lambda calculus. My concerns are due to the fact that 1. Intuitively, a variable is said to be bound if it is quantified in a lambda, as it is `x` in `(lambda (c) (lambda (x) c))`; 2. the K combinator is, indeed, a combinator. Therefore, according to the very definition of combinator, it should not feature any free variable (this is also stated by the authors at page 30, _"Lambda calculus expressions without free variables are called combinators"_). – Ilio Catallo Oct 31 '18 at 19:56
  • there is no `x` behind the `(lambda (x) ...)` there, so it is not bound - it is not even there. :) it *would* be bound if it *were* there. – Will Ness Oct 31 '18 at 19:57
  • 1
    what free variable do you see in there in the K combinator? just as you said, there isn't any. right? `c` is bound. that's it. it is bound precisely because it *does* appear free in the nested expression. in fact, "c is bound" is sloppy. the book takes care to say "`c` *appears* bound in ...". I remember having same doubts exactly for this thing, BTW. "It's bound by the lambda declaration" or something... "!???" But the question is not whether it "is bound", but whether it "*appears* bound". This helps to untangle the two, I think. – Will Ness Oct 31 '18 at 19:59
  • Let me rephrase to see if I get your argument: as the only variable in use (i.e., `c`) is bound, `(lambda (c) (lambda (x) c))` does indeed constitute a combinator, correct? The takehome message is that it makes sense to qualify variables as either bound or free only if they are in use. – Ilio Catallo Oct 31 '18 at 20:05
  • the importance of this is, IIRC, in later beta- (or alpha- (?)) conversion manipulations: if no free (conversely: bound) variable in a given lambda-expression becomes bound (conversely: free), then the transformation is valid. – Will Ness Oct 31 '18 at 20:06
  • 1
    to your last question, yes. That would seem to follow the definition fully. so, yes, that's why they always make a point of saying "*appears* bound in ...", not the more vague "*is* bound in ...". – Will Ness Oct 31 '18 at 20:07