Unlambda-clj is, as its name might suggest, a Clojure implementation of unlambda. It implements the "unlambda 2.0 standard", and passes every test that I've been able to find on the internet or come up with myself!
Running main (by way of
lein trampoline run) will start a repl, you can tell everything is working by entering
```si`k``s.C``s.l``s.o``s.j``s.u``s.r``s.e ``s. ``s.r``s.o``s.c``s.k``s.s``s.!``sri`` si``si``si``si``si``si``si``si``si``si`ki
Which should print "Clojure rocks!" ten times.
What is Unlambda?
Unlambda is an esoteric programming language written by David Madore. Unlike the typical Turing-machine based esoteric languages, unlambda is based on the untyped lambda calculus.
If you're familiar with functional programming, it shouldn't surprise you that the untyped lambda calculus is Turing-complete, however it may surprise that you don't even need lambda to achieve that. Unlambda, in fact, does away with lambda abstraction altogether, and instead uses the S and K combinators to achieve Turing-completeness (For more on this, see the Wikipedia article on SKI combinator calculus).
More about Unlambda
Unlambda functions are applied to each other with the
character. Back-quotes are by far the most common character in most unlambda
programs, as to get anything done you must perform a great deal of function
application! Every function takes exactly one argument (multiple arguments can be
simulated via currying), meaning that the back-quote notation is unambiguous.
Unlambda has the following built in functions (which are all present in unlambda-clj):
k: The K combinator. Equivalent to the following Clojure code:
(fn [x] (fn [y] x)). That is,
s: The S combinator. Equivalent to the following Clojure code:
(fn [x] (fn [y] (fn [z] ((x z) (y z)))). That is,
i: The I combinator. Returns its argument (identity). The same as
v: Void. Discards its argument and returns
c: Call-with-current-continuation. Applies its argument to the current continuation (e.g.
`<x><current-continuation>). More information on what this means is can be found in various places on the internet.
d: Delay (special form). Delays the evaluation of its argument
<f>until it is forced by being applied to another argument
<a>. When that occurs,
<a>will be evaluated before
<f>, and then
<f>will be applied to
.x: Write. For all characters
.xis a function which prints out the character
x, and returns its argument.
r: Shorthand for
.<literal newline>. That is,
rprints a newline, and returns its argument.
e: Exit. Halts evaluation, returning its argument as the result of the program.
@: Read: Reads a single character. Sets the "current character" to the value of the character read in (from
?x: Compare Read: Similar to
?xis defined for all characters
x. It compares
xto the "current character". If they have the same value, it returns
|: Print Current Character: If a value for the "current character" exists, then
`<x>.<current character>. If the current character has not been set yet, then
Additionally, this implementation discards all white-space (except when
appearing after a
?), and treats
# as an indicator to skip to the
next line (e.g. a single line comment).
For even more information, including how to actually go about writing unlambda programs, consult the official page on unlambda http://www.madore.org/~david/programs/unlambda/
Clojure to unlambda translator
Translate expression in clojure-like syntax to unlamba. Allow to define custom functions that saved in file and stored between sessions.
user=> (use '[unlambda-clj.translator :only (defu run-unlambda to-unlambda)])
Translate to unlambda:
user=> (to-unlambda (.o (.l (.l (.e (.H i)))))) `.o`.l`.l`.e`.Hi
user=> (run-unlambda (.o (.l (.l (.e (.H i)))))) Hello
Define custom functions:
user=> (defu print-number [n] (n .* i)) user=> (defu 2 [f x] (f (f x))) user=> (run-unlambda (print-number 2)) **
You can also insert "raw" unlambda code using string. E.g. we can define
force functions to delay evaluation of some function:
user=> (defu delay  "d`k") user=> (defu force [f] (f i)) user=> (run-unlambda (delay (print-number 2)) user=> (run-unlambda (force (delay (print-number 2)))) **
user=> (run-unlambda (print-number (fn [f x] (f (f x))))) **
Note: basic functions such as +, *, -, 0, 1, 2, true, false and others are not provided, so you need to write them by yourself.
Copyright (C) 2012 Thom Chiovoloni
Distributed under the Eclipse Public License, the same as Clojure.