Monday, October 16, 2006

The birth of recursion from self-application in lambda calculus

Reading Many faces of the fixed-point combinator and Y overriding self-application by Oleg Kislyov (oleg-at-pobox.com), I came to understand how to express recursive functions in lambda calculus in an elegant way. Oleg's code was written in Scheme, but it was clear that it was easily translated in pure lambda calculus. I used the Lambda calculator by Carl Burch to do this for the (recursive) factorial function:
(λf.f f) (λf.λn.if (= n 0) 1 (* n (f f (- n 1))))
Example: ((λf.f f) (λf.λn.if (= n 0) 1 (* n (f f (- n 1)))) 5)
Afterwards, I found on the CLiki Factorial page a Common Lisp translation of the above:
((lambda (f) #'(lambda (n) (funcall f f n)))
#'(lambda (f n) (if (= n 0) 1 (* n (funcall f f (- n 1))))))
This would probably look much better in Scheme, and I am beginning to understand why Scheme is regarded as a "better Lisp" than Lisp.

Just when I was contemplating "porting" the lambda expression to Ruby, here it is... well, almost. Actually, the Y combinator is used here, instead of the U combinator used by Oleg in the above articles. So, here is the true Ruby translation (actually a sample call of it):
p lambda { |f|
f.call(f)
}.call(
lambda { |recurse|
lambda { |n|
if n == 0 then
1
else
n * recurse.call(recurse).call(n-1)
end
}
}).call(5)

Monday, October 09, 2006

YALQ - Yet Another Lisp Quine

Here is a format-based Lisp quine:

(let ((p "(let ((p ") (s "(format t \"~A~S) (s ~S)) ~A)\" p p s s)")) (format t "~A~S) (s ~S)) ~A)" p p s s))

Please note that the above code should be written on a single line, and there should be a space before the last ~A, before the end of the string.

While I thought it was pretty original at the time it was written, I now discovered the quine by Dave Seaman (ags@seaman.cc.purdue.tom.edu MINUS cat) on the Lisp section of the Quine Page:

(let ((p "(let ((p ~s)) (format t p p))")) (format t p p))

This one is smarter and shorter, since p is used as a format-string for printing itself, without needing both a prefix and a suffix, but it is clearly in the same vein.

Sunday, October 08, 2006

Mapcar in Ruby

A Ruby version of Lisp's mapcar function:
require 'generator'
# One mapcar to rule all Enumerables.
def mapcar(*enums)
generators = enums.collect {|e| Generator.new(e)}
result = []
while true
begin
params = generators.collect {|g| g.current; g.next}
rescue EOFError
return result
end
result << yield(*params)
end
end
Sample usage:
qSorters = arrays.collect {QSort.new}
threads = mapcar(qSorters, arrays) {|q, a| Thread.new {q.quicksort(a)}}
This creates an Array of Threads that use the objects in qSorters to sort each element of arrays.
Please note that the QSort class is user-defined and omitted here for brevity (and sanity).
The above mapcar is based on recipe 7.9, pages 256-257 of the Ruby Cookbook, specifically the interosculate function.