Diary of Clojure Learner

I am trying to learn clojure. As my knowledge would increase, i would add more stuff here :

Clojure is a functional language. A functional language gives first priority to functions. I have come from OOPs background, and i have just started learning clojure. I do not know how to create classes in clojure or is it possible or not. There is very little that i know about what is it like to be being functional for a language.

Lets see what i have learned till now.

So one thing that i want to emphasize is these functional languages follow post-fix style of programming. Like if you want to add two numbers, you do

                                       (+ 1 2)
 i.e. operator comes first and then the arguments.

Next, Every new block comes inside braces '(' and ')', as you could see in the above example too.
The first thing after the opening brace is taken as function name and then comes its arguments.

An inbuilt data-structure is list which is represented as
             '("apples" "bananas" "oranges" 2 4)

Opening and closing braces are here too in the list. So how does it know, whether what we have written is some code or a list. Actually, Every line of code and the whole code is nothing but a list in clojure. But to differentiate between things, quote ' is given, which prevents the code from evaluating itself.

so '(something) becomes (quote something) which return something. Hope that you could see the function quote in there.

Another data structure given is vector represented as
   [ "apples" "bananas" "oranges" 2 4]

A inbuilt function conj is provided which adds value to the given list or vector.
           (conj [1 2] 3)
This would give [1 2 3] as output.
           (conj  '(1 2) 3)
would give (3 2 1)

Remember your Data-structures, it is easy to add to the front of list and back of vector. :)

But as i am learning i am feeling that a lot of code is like ' or ( which makes things difficult to debug if you forget to leave something here or there. Lets see what i learn tomorrow...


Next day :
What is it like to be a Functional Language ?
Functions are the objects. You can pass them around in arrays or anything. Do work on them.
    The OOper in me says.. so what... I can do this with function pointers in C , C++. ha ha...Language constructs like if-else, variable assignments all are functions only. They return data only.

Stateless:
Each function knows only itself. It takes some input and gives some output.
Like your math functions from some domain to some range.
It can not modify anything outside of the function.
    The OOper is shouting... This is going to be difficult..

Immutable states:
All the datastructures are immutable. They just can not be changed. You only create new and dispose off the old ones.
    The OOper has hit the panic button.
But wait a minute.. What are the advantages ?

If we can not change any global state, we create functions which are just pure. Only looking at this part of the code, can make feel confident that this is perfect.

Think about those endless hours of debugging and listless bugs (many still lingering in the code) in c or cpp which lastly found to be modifying some global state or corrupting some data. And... here comes some respite.. No concurrency issues. No multithread problems.. since all the data is immutable.

But then how would i programme ? That is why i am going to learn more about this language to find how do we solve these problems in a different way.

    The OOper in me.. that would be a nice learning...

Next Day:

ok today i learned something about the vectors and list. Why creating new of them is not bad ? both runtime wise and memory wise.. let the magic begins.

They use kind of  hash-maps. I do not know the actual algorithm and data-structure. But think about this.

You want a new list which just have one more element added to front of an existing list. Since both list would finally be immutable, one can keep references to start and end position of both list.
With hash-maps, more power comes. Like constant look for vector. It must be a complicated data structure, but it is already given to us. We do not need to take any problem for it.


variables can have these symbols too ? - _ and many more.
    well i do not like this - it makes reading program difficult.
user of colon :
    colon differentiate between keywords and variables.
    one example that i know about is their use in maps.
        (let [ myMap {:a "a", :b "b", :c 2}]
            (myMap :a))

    This would output "a".
    Just look at ':' above and forget about 'let' and other things.

    :a is a key for the map whose value is "a"

    { somekey somevalue } is used to define the map

nil : is null of clojure and evaluates to false.

Next Day:
so today i learned some basics about the language :
like
   
namespaces :
    namespaces are a wrapper over our symbols like functions.
    one can have same named functions under different namespaces.

    so if we have two namespaces like animal and insect
    and one function walk in both of them :
        then we can access them like
            animal/walk
            insect/walk


        so just to write a complete function example taking steps to walk:
            (animal/walk 5)
            (insect/walk 2)


        [ i do not yet know how to create namespaces yet ]

    so this takes us to our next thing which i think we have already discovered :
function calling:
    so there is a list - whatever comes first in the list is function name and then its arguments like
    (add 1 3 4) would give 8
    and
    (first '(1 2 3 4)) would give 1
    here we have a function first which takes a list. see the quote ' before the list to tell that what follows is a list data-structure.


Reader and Executor:
    In many languages i have seen, i did not find this thing. It looks cool :

    In programming, we give some text of code as input with produces some data-structure like Abstract-Syntax-Tree, which is composed of lexical units or tokens.
    In clojure, every thing is token in the code itself. Is it not ?
    Every piece of code is inside a list, giving it a proper structure. Postfix ordering, every statement returning some value it all points towards this thing. The program that takes the code and reads it and as soon it has find something that can be executed, it sends it forwrad. This program is called Reader.

    The one that executes the program is called Executor. :)

Keywords:
    Like keywords in other languages there are also some important and exceptional things in clojure too like
    if, def etc..

    But i think that unlike other languages, they do not go against the philosophy of language, like
    in clojure if can be thought as a function talking three parameters as
    (if condition a b?)
    which means if condition is true a is returned else b is returned. '?'' says that b is optional.

    for example:
    (if (> 1 0) (add 1 3) (sub 1 3))

    This is a valid clojure statement given we have two functions add and sub.
    Here condition is a function which would return true or false.
    Here it woudl return true as 1 is greater than 0.
    So it would execute add function with two parameters 1 and 3 and finally return 4.

    so one can write
    (if (= (if (> 1 0) 4 2) 4) "returned 4" "returned 2")
    However, in c or cpp or java, if statement does not return anything. They would give compiler errors.


Next Day:

Function calling for the objects:
Dot (.)
    (. classname static-function arguments*)
    (. object function arguments*)


   e.g. (. cow eat grass) ;// cow.eat(grass)

Namespace creation:
    (clojure.core/in-ns (quote alligator))  // create a new namesapce alligator
    (clojure.core/refer (qupte clojure.core))   // put everything of clojure.core namesapce in namespace alligator. core has functions like + , *.

    (def harry (+ 3 6)) // add a function harry to current namesapce alligator

fn :
    Functions are defined by fn
        (fn add2 [a b] (+ a b))
    gives a function add2 that take two arguments a and b and returns its sum

def:
    (def name object)
    (def beetle 3)  // bettle is a var that points to 3

    (def increment (fn [x] (+ x 1 )))

let:
    is for defining variables with some value:
        (let [x "foo" y "bar"]
            (println x)
            (println y)
        )

    This would print "foo" and "bar".

    Here `let` takes a vector. Inside that vector name-value pairs come, like "foo" for x and "bar" for y.
    Then any number of expressions can come that would get executed.

    Let returns the return value of last executed function.

do:
    do executes any number of expressions given to it.
    like
        (do (+ 2 2) (+ 3 5) (* 4 5))

Next Day:
Tail recursion in clojure:
    Calling the function from inside itself is called recursion.
    when we call it at the end of the function, it is called tail recursion.
    One optimization that can be made with tail recursion is that we do not need the current function 
frame when we are going to recursive one. so, we do not take any stack as we override the current
function frame with the next recursive frame.

    This optimization saves memory, prevents stack-overflow errors.

    in lisp we have `recur` to do it

    ((def recurFuncExample
        (fn [a]
            (if (< a 10)
                (recur (+ a 2))
            a)
        )
    ) 2 )

    This `recurFuncExample` is a function that take a argument,
    if the number is less than 10, it calls itself with 2 added to argument,
    otherwise prints number.
    We called the function with argument 2, can you find the output ? It is in the question :P


Loop-recur pattern:    we can use recur without function also, we just need to specify from where should we jump to for the execution. This is told by `loop`.

    Loop takes a vector with name-value pairs that is like defining variables.
    Then we can have expressions. Now if we write recur after that, it would go back to loop with the new parameters.

    see the example:
        (loop [x 2]
            (if(< x 5)
                (recur (+ x 1))
             x)
        )


    So, when we call `recur`, it would go back to `loop` with the new argument ( number + 1).


Compile time declaration:
    so with the namespaces, one thing that we should know, if we are refering to some variable, function etc, then it should be atleast be declared. Its body or definition can be given later :

    so something like
        (def foo (fn [x] (bar x 1)))
        (def bar (fn [x] (+ x 3)))


    would give error as it would not be able to find bar.
    so, we can do :
        (def bar) ; // declaration here.
        (def foo (fn [x] (bar x 1)))
        (def bar (fn [x] (+ x 3)))



Macros:
    They are the function that work on reader data and modifies the code itself.
    so they are like c macros that replace the text in the program before it get executed.
    Clojure docs are saying that they can be very powerful, since clojure is dynamic run-time language, i would like to see the power of macros.

    just found that `defn` is a macro that helps in writing smaller code
        (def myFunc (fn [x] (+ x 2)))
    can be written with macro `defn` as
        (defn myFunc [x] (+ x 2))

Every data structure has a map that tells metadata about that object:
    One of the parameters in the map is `macro` : which is true for a macro.

Creating a macro:
    (defmacro name [parameters*]
        expression*)

Variatic function:
    A function can take variable number of arguments
    In code:
        (def foo (fn [x & y] ... ))
    so (foo 4) and foo(4 5 6) both would work.
        y would have [5 6]

Why are vars mutable ?    vars are functions. why do we want to change the functions.
    Changing the function means changing the behavior, like upgrading your system.
    Some systems, like servers, require this thing, which can be great for them, that things get changed in run-time.

Ref:    Refs are mutables which can change during transaction.
    If refs changes during transaction, then we would reattempt the transaction, since old data is no longer valid. This reattempt is done with the updated data. I do not know a example, so i also do not understand it much..

One important thing that i want to say here is that clojure runs in JVM and it can access all of the classes of Java. so, there are plenty of apis available for eveything.

Type hinting :
    Although, clojure is dynamic language, if we want we can tell the types and let it use basic data-types of JVM for optimization purposes and not use box-unboxing of variables.   


These notes have been made by looking at the video tutorials at : clojure videoes






Comments