sans-hubris
05-16-2002, 09:04 AM
"I heard a rumor that lambda calculus doesn't have recursion because it doesn't have named functions! It must be true because I can't think of a way to do anonymous recursion."
"It is a rumor, and nothing more! Trust me or go ask Alonzo Church or Alan Turing if you don't believe me. However, recursion may not be what you think it to be. In all reality, it's nothing more than syntactic sugar! This is why lambda calculus can get away with having anonymously recursive functions."
So, you're job is to write, in any language, a Y combinator. "What's a Y combinator?" some may ask, while others are trying to dig up their old LISP or Scheme source code. The Y combinator is exactly what is needed for anonymous recursion. Take the following pseudo-code, for example:
lambda length(l) //lambda declares a function
if empty_list(l) then //empty_list returns true iff l has no elements
return 0
else return 1+length(cdr(l)) //cdr returns the list of elements after the first element
What happens if we change the name of length?
lambda eternity(x)
eternity(x)
lambda length(l)
if empty_list(l) then
return 0
else return 1+eternity(cdr(l))
So now we can only get the size of a list with length zero. What about a list with one element? Hopefully you'll have some idea of what's coming next.
lambda eternity(x)
eternity(x)
lambda length0(l)
if empty_list(l) then
return 0
else return 1+eternity(cdr(l))
lambda length1(l)
if empty_list(l) then
return 0
else return 1+length0(l)
//if you don't like my naming scheme:
lambda length1b(l)
if empty_list(l) then
return 0
else return 1 + (lambda(n) //anonymous function taking one argument
if empty_list(n) then
return 0
else return 1+eternity(n))(l) //this is passing the list 'l' as an argument to our anonymous function
I'll let you do length2 however you wish. Consider the following function:
lambda eternity(x)
eternity(x)
lambda length_maker(length) //this function requires a function to be passed to it
lambda(l)
if empty_list(l) then
return 0
else return 1+length(cdr(l))
//the following defines a function that, when called, will first call lengt-maker with the argument eternity to get another function that takes a list, and returns the size of a list with zero elements in it
define length0a length-maker(eternity)
Hopefully you're getting the point that recursion is nothing more than a name problem. This is where the Y combinator comes in:
lambda Y(recfun)
(lambda(f)
(f f)) (lambda(fn)
recfun(lambda(x) (fn(fn))(x))
Ich! Sorry, that's a bit ugly. If you're familiar with how lambda calculus works:
(lambda (f) ((lambda (x) (f (x x))) (lambda (x) (f (x x)))))
Or you can just try following the Scheme version:
(define Y
(lambda (recfun)
((lambda (f)
(f f))
(lambda (f)
(recfun (lambda (x) ((f f) x)))))))
Basically the challenge is to write the Y combinator in whatever language you would like. If this description isn't enough for you, you may try this (http://www.everything2.com/index.pl?node=Y%20operator) one or just go on google and look it up. It would be interesting to see this coded in non-functional programming languages.
To make sure it works, you must also code a function that uses the Y combinator. To get you started, here are some ideas: factorial function, Fibonacci, quicksort, etc.
"It is a rumor, and nothing more! Trust me or go ask Alonzo Church or Alan Turing if you don't believe me. However, recursion may not be what you think it to be. In all reality, it's nothing more than syntactic sugar! This is why lambda calculus can get away with having anonymously recursive functions."
So, you're job is to write, in any language, a Y combinator. "What's a Y combinator?" some may ask, while others are trying to dig up their old LISP or Scheme source code. The Y combinator is exactly what is needed for anonymous recursion. Take the following pseudo-code, for example:
lambda length(l) //lambda declares a function
if empty_list(l) then //empty_list returns true iff l has no elements
return 0
else return 1+length(cdr(l)) //cdr returns the list of elements after the first element
What happens if we change the name of length?
lambda eternity(x)
eternity(x)
lambda length(l)
if empty_list(l) then
return 0
else return 1+eternity(cdr(l))
So now we can only get the size of a list with length zero. What about a list with one element? Hopefully you'll have some idea of what's coming next.
lambda eternity(x)
eternity(x)
lambda length0(l)
if empty_list(l) then
return 0
else return 1+eternity(cdr(l))
lambda length1(l)
if empty_list(l) then
return 0
else return 1+length0(l)
//if you don't like my naming scheme:
lambda length1b(l)
if empty_list(l) then
return 0
else return 1 + (lambda(n) //anonymous function taking one argument
if empty_list(n) then
return 0
else return 1+eternity(n))(l) //this is passing the list 'l' as an argument to our anonymous function
I'll let you do length2 however you wish. Consider the following function:
lambda eternity(x)
eternity(x)
lambda length_maker(length) //this function requires a function to be passed to it
lambda(l)
if empty_list(l) then
return 0
else return 1+length(cdr(l))
//the following defines a function that, when called, will first call lengt-maker with the argument eternity to get another function that takes a list, and returns the size of a list with zero elements in it
define length0a length-maker(eternity)
Hopefully you're getting the point that recursion is nothing more than a name problem. This is where the Y combinator comes in:
lambda Y(recfun)
(lambda(f)
(f f)) (lambda(fn)
recfun(lambda(x) (fn(fn))(x))
Ich! Sorry, that's a bit ugly. If you're familiar with how lambda calculus works:
(lambda (f) ((lambda (x) (f (x x))) (lambda (x) (f (x x)))))
Or you can just try following the Scheme version:
(define Y
(lambda (recfun)
((lambda (f)
(f f))
(lambda (f)
(recfun (lambda (x) ((f f) x)))))))
Basically the challenge is to write the Y combinator in whatever language you would like. If this description isn't enough for you, you may try this (http://www.everything2.com/index.pl?node=Y%20operator) one or just go on google and look it up. It would be interesting to see this coded in non-functional programming languages.
To make sure it works, you must also code a function that uses the Y combinator. To get you started, here are some ideas: factorial function, Fibonacci, quicksort, etc.