After long chat with my friend who is Ocaml ( Objective Caml ) fanatic on topic of Lisp. I decided to get my hands on Clojure. Is there a better idea to learn language other than to write a crapy language learning tutorial ? Sure! but i will go with this one :D.
Lisp
Before i tried Clojure i had few “trips” to Lisp world but i was always stroked by amount of half finished vm’s and implementations that are far from being production ready. For example chicken, scsh, sketchy, mit-scheme, bigloo. Some of them are more some less production ready but none of them is ready for anything real. The most production ready lisp thing i saw in my life was elisp
YES f*cking EMACS
lisp.
But I’m not any expert in lisp world!
Scheme
Scheme is a dialect of Lisp that implements subset of language, in scheme code and data has same form which is a massive game changer. Scheme has super duper hiper mega MACRO building capabilities. And it is probably its biggest problems…
Lisp Hacker’s
I remember when my friend was hacking in lisp, i remember when i was trying to hack stuff in scheme. So scheme is a trap! First stage of lisp/scheme hacker is to build scheme interpreter in scheme, when he finishes this he tries to implement scheme interpreter in his interpreter… Second trap is when he realizes that he wrote enough amount of scheme interpreters and he moves to implementing new features into his interpreter in interpreter in interpreter ( and yes ‘ready’ means that 8/10 runs stuff passes, some crash and half of features don’t even exits so called “junk features” ). So his dialect gets better than Haskell lazy evaluation, better etc… at this stage he has self bootstraping half working interpreter of his language that had no docs and nobody except his can use it and even if he can he must be on drags to make the lazy evaluation happen. Next stage of course is starting to do AI in scheme. So the point is that no shit gets done, its all conceptual work. If Da’vinci would program in Lisp he would not cut of his ear, he would cut of his head.
Life of ()
I wrote some borderline rant on lisp hackers and this was supposed to be micro tutorial on scheme. Well i took the Lisp way of “getting shit done” :D. If you don’t know that lisp bread and butter are (
and )
you should probably run away.
Naow!
So why Clojure ?
Clojure seems to be production ready stuff that can “get shit done”. It support concurrency (with STM – Software Transactional Memory) it is Scheme’y / Lispy and I have read that its hip in Open Source magazine. Thats enough to start learning yeah ?
No! But i want to learn it and write some stuff about it. It seems to be so different from other languages, RP notation and the whole community of Stallman like people.
Clojure runs on JVM ( Java Virtual Machine ) and beside Java being biggest troll language next to C++ ever! JVM is really good. It makes stuff really portable and its good for building stuff like backends for servers. Same goes with Scala using JVM, actually JVM is solid! ( coming from me Java hater ). Its not like some f*cktard writing in “Open Source Magazine” that C++ enables you to write portable code. No, writing os portable code in C++ is not easy, its hard and full of pain.
Getting s*it on your box
First thing you have to do is to install Clojure. This is the easy step. Just visit http://clojure.org/. I installed it using macports by running sudo port install clojure
but for more into i would suggest going to:
- Minimum jar needed to start REPL http://clojure.org/getting_started
- Downloads for latest version http://clojure.org/downloads
- Brew / Macports search “clojure”
- In case that nothing else work, go to https://github.com/clojure/clojure and look for “build from source instructions”
Next you will want to install leiningen
this is a build tool for Clojure. same procedure. either sudo port install leiningen
or http://leiningen.org/ for more instructions.
Running repl and first code!
Enough of this sh*t lets do some stuff. First to run repl you need to do following.
1
|
|
I mix it with cjl
but thats because i’m a noob.
This should prompt you with something like this
1 2 3 |
|
Success!!! We can now try to evaluate some simple stuff.
So now normal person would try to type something like 2 + 6
bad idea! Expressions in Lisp starts and ends with ()
so if you see things like (((((((((((((((((((((((((((((
or )))))))))))))))))))))))
you know something is happening :D (second one more commonly)
1 2 3 4 5 6 |
|
RPN now i should quote link to wikipedia on Reverse Polish Notation. (I’m Polish so it is kind’a like looking at my back and trying to read sign on t-shirt). Here you go http://en.wikipedia.org/wiki/Reverse_Polish_notation Reverse polish notation simple words is a stack notation. Where you put operator on stack and then arguments. Or so called prefix notation. C, Java, Ruby are all infix notation eg. 2 + 6
while lisp / scheme is prefix notation aka (+ 2 6)
on reality its so cool that you don’t have to repeat your self and you put operator, function only once and a list of arguments eg. (+ 1 2 3 4 5)
. So lets try it out.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
We can see that those examples work in REPL nice!. But wait there is something different between (/ 4 5)
and (/ 4 5.0)
. Yes! Clojure has built in support for rational numbers so 4/5 is a rational 4/5 not rounded estimate of 4/5 while result of evaluating 4/5.0 is a floating point number. Lets see what happens if we will try to do 1/3
1 2 3 4 |
|
Yeah the second one is not really accurate. Or is it ?
1 2 3 4 |
|
Not really…. it should be something like 0.(6) :)
So this is how you invoke functions, built in functions. But what if you would want to comment something out ? because its a useful info about new scheme dialect you are building?
Comments
You do comments using ;
everything after ; is getting ignored!
For example:
1 2 3 4 5 |
|
defn
First thing that makes people happy usually while learning new language is the moment when guy that tries to explain whole concept helps them write first function! Yes thats what i will do now.
To define a function we use defn
(old lisp grinders will connect it with def
yes!) that defines a function for us, so to it we need to supply name of function, or the symbol that this function will be bind to, arguments and body like this.
1 2 3 4 |
|
Next we can invoke it eg. (multiply-by 3 4)
its worth mentioning that you can use -
in function names. But what is really happening ? this is two part thing. First we have def
and second we have fn
def binds symbol name with expression or value and fn
return a function. So it is “like lambda” in fact it is lambda.
Lets go with example.
1 2 3 4 5 6 7 8 9 10 |
|
This is slightly more complex but also should be easy. In first line we use fn
to define function with one parameter called base this returns a function. In line two we do the same but this function is returned and passed and argument of 5 and evaluated to 6. In line three we define symbol troll-symbol with value of 7 we obviously can’t evaluate a value so we get exception! It’s all fine because its value. But we can use it like in last line, where we add to value of troll-symbol effect of evaluation of function that we defined passed with argument of 5.
Don’t be afraid :D. All we did here is explained what defn
do, basically defn is just composition of def and fn. Lets you specify symbol that function returned by fn is bound to.
Defn simply saves us key strokes :) Like using Emacs :D this can lead to RSI. =)
1 2 3 4 5 6 7 8 |
|
This exactly shows what happens when you use defn, you get function from fn and bind it to some symbol. That’s it. Its good to have some play with all this brackets :) its fun! try defining something on your own :D
Hello world
So every tutorial has to have something like hello world program! In my tutorial there is space for Hello World also :D
All you need to do is to create a file called hello.clj
and type this in!
1
|
|
When you will run it using clj hello.clj
you will see something like this
1 2 |
|
Lambdas!
So i mentioned something called fn
for creating functions. But sometime you need a function ad’hoc eg. when you pass it to map
function this is done by using different syntax.
1 2 |
|
You can still use old syntax but this is just faster to type. Remember that %1, %2 … refer to arguments that are passed to this lambda.
Lists and Vectors
Like in all programming languages we have lists and vectors. Those are built in. Syntax for List is simply '()
eg. '(1 2 3 4)
and for vector aka “array” its []
eg. [1 2 3]
. NO COMAS!
1 2 3 4 |
|
Lets do something useful with them! print them out naow!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
It is map… so it is ugly because result from println
is nil so we printed out contents of vector and list but its ugly.
Map is a high order function that takes function and list/array/sequance of arguments, applyies and evaluates funtion on each argument and stores results of this in a list that is returned at the end :) eg. (map (+ %1 1) (1 2 3))
will give [2 3 4]
.
Lets try to do it with doseq.
1 2 3 4 5 |
|
Works!
Glossary
REPL – Read Eval Print Loop. Simply language console in which you can run code and see results without typing code into file and running interpreter on it.
Lisp – On of the biggest language trolls or only language worth learning. Still can’t decide
Jar – Java archive that contains code, can contain also jam. I like jam.
Summary
This is just the first part of the tutorial i hope you liked it, just covers the very basic of defining and evaluation functions.