Mockingbirds and Simple Recursive Combinators in Ruby
github.com
github.com
http://www.cs.virginia.edu/~evans/cs655/readings/mockingbird...
Combinators are the basic building block of combinatorial logic. Simply, they are functions that permute, group, repeat and/or eliminate their arguments.
E.g., The T (thrush using the bird naming convention) combinator takes two args and swaps their order: Txy = yx.
The B (bluebird) combinator groups it's 2nd and 3rd args (overriding the default left-associativity): Bxyz = x(yz).
The M (mockingbird) combinator takes a single arg and repeats it: Mx = xx.
The K (kestrel) combinator takes two args and eliminates the second: Kxy = x.
There are two schools of 'lambda calculus' that use a set of base combinators to build arbitrarily complex ones. The first school uses B, M, T and I which is the identity function: Ix = x. The other school combines B, M and T into a single combinator that permutes, groups and repeats with one application. It's called S (starling): Sxyz = xz(yz). This latter school uses S together with K.
Whether using B/M/T/I or S/K/I, you can build up pretty much any other combinator:
B = S(KS)K.
E.g.,
S(KS)Kxyz, applying the leftmost S =
(KS)x(Kx)yz, dropping the parens (which are still implied when not present due to the left-associativity) =
KSx(Kx)yz, applying the leftmost K =
S(Kx)yz, applying the S =
(Kx)z(yz) =
Kxz(yz) =
x(yz) = Bxyz.
T = ((S(K(S((SK)K))))K)
M = ((S((SK)K))((SK)K))
I = SKK. E.g., SKKx = KK(Kx) = K(x) = x = Ix.
V**xyzwv = xyvzw.
V** is spelled: (S(K((S(K((S((S(K((S(KS))K)))S))(KK))))((S(K(S(K((S((S(K((S(KS))K)))S))(KK))))))((S(K((S((S(K((S(KS))K)))S))(KK))))(S(K((S((S(K((S(KS))K)))S))(KK)))))))))
The up-shot of all of this is that any computer program complete with arithmetic functions, boolean/propositional logic, list processing, etc. (i.e., Turing complete) can be expressed as a sequence of these base combinators. There are other practical (less theoretical) applications in programming. E.g., Using the T/thrush combinator to improve readability: http://debasishg.blogspot.com/2009/09/thrush-combinator-in-s... .The Y combinator, for which this site is named, encapsulates recursion (i.e., a fixed-point combinator). It's spelled: S(K(SII))(S(S(KS)K)(K(SII))).
Now, that is interesting. It mirrors some thoughts I've been having lately but unable to express fully. Tell me more.
The execution of such a program on an actual "Turing machine" probably wouldn't be as performant as on our modern complex-instruction-set processors. Then again, I think the intent is to think of it as executing at the same speed at which a mathematical equation is true. I.e., You could go out and count 999 things or just accept that nine nine nine is a concise symbol representing the same procedure. The SKI representation isn't as terse but it's still just a symbol.
You can also read more at http://en.wikipedia.org/wiki/Lambda_calculus#Encoding_dataty... ...though it doesn't seem as gentle (read hand-holdingly verbose) as To Mock a Mockingbird.
Also a Combinator Calculator.
https://github.com/raganwald/homoiconic/blob/master/2008-11-...
Thanks for pointing out an important omission. Updated.
You just pass the function as a parameter to call, like this:
sum_of_nested_list.call(sum_of_nested_list, [1,[2,3]])
Right? What am I missing?There’s a practical example of using the Y-COmbinator to make auto-vivifying hash tables in one of the links.