Saturday, September 25, 2010

Lesson 3 - User defined functions in Clojure

In this lesson we will roll out our own function in Clojure.

We'll use spit and with-out-str to write to file. But instead of emit, we'll use the emit-element function for our tags.

Type out the following code and save it as hellohtml.clj.
//hellohtml.clj

(use 'clojure.xml)
(println
 (with-out-str
  (emit-element
   {:tag :html :content
    [{:tag :body :content
     [{:tag :h1 :attrs {:style "color:red"} :content["My Homepage"]}
      {:tag :div :attrs {:style "text-align:center"} :content["This is the content"]} ]}]})))
Run it using lein exec
$ lein exec hellohtml.clj
<html>
<body>
<h1 style='color:red'>
My Homepage
</h1>
<div style='text-align:center'>
This is the content
</div>
</body>
</html>
If you compare it to the helloxmlfile.clj from Lesson 2, you should have an idea of what the above code does.

I know what you're thinking. SO MANY BRACKETS! Relax, you'll be fine.

What do we have here? HTML wasted on stdout. Let's save that to file by replacing println with spit <filename>.
//hellohtml.clj
(use 'clojure.xml)
(spit "hellohtml.html"
 (with-out-str
  (emit-element
   {:tag :html :content
    [{:tag :body :content
     [{:tag :h1 :attrs {:style "color:red"} :content["My Homepage"]}
      {:tag :div :attrs {:style "text-align:center"} :content["This is the content"]} ]}]})))
Run it using lein exec.

As expected we have a file called hellohtml.html with the code that was earlier sent to stdout.

Now let's generate more pages for our fictional website. We're going to be consistent with our minimalist design and the only parts that will change are the filename, title and the content. Since that's the case, why repeat the code for each page when you can roll your own function to do exactly that.

Let's create a new file called hellofunchtml.clj and modify our exisiting code so it looks like this.
//hellofunchtml.clj
(use 'clojure.xml)
(defn generate-page [filename title content]
  (spit filename
   (with-out-str
     (emit-element
       {:tag :html :content
        [{:tag :body :content
         [{:tag :h1 :attrs {:style "color:red"} :content[title]}
          {:tag :div :attrs {:style "text-align:center"} :content[content]} ]}]}))))

(generate-page "about.html" "About Me" "There's nothing to say.")
(generate-page "contact.html" "Contact Me" "Here's my email and phone. Spam me.")
(generate-page "faq.html" "FAQ" "Why was six afraid of seven? It wasn't. Numbers are not sentient and thus incapable of feeling fear.")
(generate-page "index.html" "Index" "Welcome to my homepage")
Run it using lein exec
Congratulations! You define functions in Clojure using defn. defn takes a function name, a set of params in a vector, and a function body as its arguments. defn also takes two more optional arguments doc-string? and attr-map?, which we will cover in another lesson. In the last lines we called the generate-page function passing it the three required parameters.

Friday, September 24, 2010

Lesson 2 - Clojure Functions

In Lesson 1 we saw two Clojure functions in action. Spit and eval. Clojure comes with a set of functions available to you by default. These functions reside in the "clojure.core" library. Have a quick look at the available functions in clojure.core at the link given below and come back here.
https://clojure.github.io/clojure/clojure.core-api.html#clojure.core

Did you notice "+" "-" "/" "*" among the available functions? Yep! These are functions in Clojure. Try the following function in the clojure REPL. (To run the REPL just run clojure without any arguments).
(+ 1 2)

In Clojure every thing you do is with functions and functions only. In addition to the Clojure core functions you have the clojure.contrib library, with additional functions contributed by a bunch of nice people. Then you have third party libraries for doing various stuff. And thats not all. You have the whole load of java functions available to you in Clojure.

We're going to output some XML to stdout using emit.

Type (emit "hello") in a file called helloxmlfile.clj and run it using lein exec.
//helloxmlfile.clj
(emit "hello")
and
$ lein exec helloxmlfile.clj
BOOM! Wall of errors.

Scroll up through the wall and you'll see some English that might make some sense.
"Unable to resolve symbol: emit in this context"

What this means is that the Clojure compiler couldn't understand what or who you were referring to when you said 'emit'.

The emit function is part of the namespace clojure.xml, which is not imported in the lein REPL. You could use spit and println in the previous examples because they're part of the clojure.core namespace, which is imported when the lein REPL starts up. (Fun exercise: Type (all-ns) in the lein REPL to see all the available namespaces. Don't bother if the output doesn't make any sense now.)

So, we're going to tell our Clojure compiler where to look for, when we say emit, by using 'use'.
// helloxmlfile.clj
(use 'clojure.xml)
(emit "hello")
and
$ lein exec helloxml.clj

<?xml version='1.0' encoding='UTF-8'?>
hello
No error wall! Sweet. But, that's not enough XML.

Make your helloxmlfile.clj look like this and run lein exec again.
///helloxmlfile.clj
(use 'clojure.xml)
(emit {:tag :parent :attrs {:value "Hello"}
:content[
{:tag :child :attrs {:value "World"}}
{:tag :child :attrs {:value "Clojure"}}
]})
and
$ lein exec helloxml.clj

<?xml version='1.0' encoding='UTF-8'?>
<parent value='Hello'>
<child value='World'/>
<child value='Clojure'/>
</parent>
The parent and child elements come from a map, a data structure in Clojure, with alternating keys (:keys) and values. A key can be a value. A map can also be a value. The content is a vector that contains a map. We'll delve into keywords and vectors and maps later.

What we have now is some XML that is wasted on stdout. Let's save that to a file using what we've learnt earlier.

Combine spit and with-out-str to make your program look like this.
///helloxmlfile.clj
(use 'clojure.xml)
(spit "hello.xml" (with-out-str (emit {:tag :parent :attrs {:value "Hello"}
:content[
{:tag :child :attrs {:value "World"}}
{:tag :child :attrs {:value "Clojure"}}
]})))
And run it with lein exec.
$ lein exec helloxml.clj
There's no output on the screen. That's excellent because if you've been paying attention, we were outputting XML to file.

Check the contents of hello.xml.
$ cat hello.xml
<?xml version='1.0' encoding='UTF-8'?>
<parent value='Hello'>
<child value='World'/>
<child value='Clojure'/>
</parent>
Well done.

Alright! To sum it up, we just learnt to send the output of our Clojure program to file. Writing XML. A bit about namespaces. Using 'use'.

Lets roll out our own Clojure function in the next lesson.

Installing Clojure 1.2

To install Clojure 1.2 create a folder for clojure files in your file system. Lets call the folder clojure. Download the following files into the folder.
clojure-1.2.0.jar from here http://build.clojure.org/releases/org/clojure/clojure/1.2.0/
and
clojure-contrib-1.2.0.jar from here. http://build.clojure.org/releases/org/clojure/clojure-contrib/1.2.0/

Clojure requires java JDK so if you don't have it installed then you can download it here.
http://www.oracle.com/technetwork/java/javase/downloads/index.html

For Linux, create a shell script called clojure with the following lines and put it in your command path.
#!/bin/sh
java -cp "path/to/clojure/*:$PWD" clojure.main "$@"


For windows create a bat file called clojure.bat with the following content and set your windows path to the clojure folder.

@echo off
java -cp "path\to\clojure\*;." clojure.main %*

Thursday, September 23, 2010

Lesson 1 - Hello Clojure

(spit "hello.txt" "Hello World! Hello Clojure")

Type the above code into a text editor and save it as "hello.clj". Now open a terminal command/window and run the program by typing "lein exec hello.clj" into the command line. You will see a file called "hello.txt" created in the same folder, with "Hello World! Hello Clojure" as its contents. Thats your first clojure program!

Of course you need to have Clojure, lein and lein exec installed on your computer, otherwise the "lein exec hello.clj" command will not work. If you don't have all of that installed, here are some instructions to get you upto speed.
http://fasttrackclojure.blogspot.in/2015/02/installing-clojure.html

Now let us look at the code. We see a Clojure expression in the parenthesis, whose first element is a function called spit. spit takes two arguments, a file name "hello.txt" and string which is the content of the file to be written (spit into).  You can see the documentation of the spit function here. http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/spit.

The above expression is called a list, and the expression is evaluated immediately on execution. This list is also a function call. In Clojure a function call is just a list whose first element resolves to a function. Now try this

'(spit "hello.txt" "Hello World! Hello Clojure")

Add a quote ' to the beginning of the list and run your program again. (Delete the hello.txt file before executing your program). Now see what happens. Nothing. The list expression is not evaluated now. Your list expression is a piece of data now.

Lets do this now.

(eval
  '(spit "hello.txt" "Hello World! Hello Clojure"))

Bam! Your quoted piece of data is evaluated again! We wrapped the quoted expression in another list, which calls a function called eval, and we passed our quoted list as an argument to it. Here is the doc for the eval function. http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/eval.

Your code can be data and your data can be code. Welcome to Lisp! Clojure is a language based on Lisp. And we are already beginning to see the power and simplicity of the language.

Are you already excited about Clojure like I am? Then go to Lesson 2.