Friday, September 21, 2012

Test Buddy: Bennie

For you slow running tests... you now have a friend. His name is Bennie.

Friday, September 14, 2012

Source-Learning-Closure: Day 3

So the start of the 3rd day of digging in Clojure's source, I'm scanning through the code looking for something that I want to dig further into. I'm finding my self relatively happy with the progress I've made so far. Looking over the various functions, I'm noticing that it looks a lot less foreign now.

(cast) calls java's cast, passing in a class and a class name to cast to. (to-array) calls clojure's java wrapper to toArray(), (vector) has a bunch of overloads to constructing a vetor, and so on. Much of those and the one's like (nil?), (false?), (not), and such are really straight forward, many of which just call the java code underneath. All of these become just needing to read up on whats available for our use.

For the most part, I'm scanning the code and all is well. Then I get to the functions for (if-let) and (when-let) and I'm taken back again.

https://github.com/clojure/clojure/blob/1.3.x/src/clj/clojure/core.clj#L1666

I'm reading them a few times, and although I can follow the code, I'm not really sure what they are doing. I also notice that I'm not as comfortable with (let) as I want to be either. So I'm going to look at (let) in more detail first.

I read over the docs and some other info else where like this. I get a better feel for it. I just needed to work through some examples. I won't bore you with to many. The idea with (let) is you create a local scope that you can manipulate your data with.

As I'm digging through let I also run into the (->) function. That one apparently runs through a group of functions in order that you give them. I won't go to much into details about this one here as this post will get really long with every derail, but I figured I'd mention it in passing as I'm about to use it, and I myself didn't know what it was until just now.

user=> (let [message "rawr"] (println message))
rawr
nil

user=> (message)
java.lang.Exception: Unable to resolve symbol: message in this context (NO_SOURCE_FILE:27)
user=> (let [a 1, b 2] (+ a b))
3

user=> 
(let [age (- 2012 1979), decade 10, century 100]
  (-> (- century decade) (+ age))
)
123

That local declaration/logic peers into the future, a decade less than a century from now, to tell me how old I will be. Here's something else I noticed while looking at the examples. I really don't like it for these examples, but I'm sure there's use for it else where.

(let [a 1, b 2] (+ a b)) ; earlier example
3

(let [[a b] [1 2]] (+ a b)) ; can also be written this way
3

These two are the same call, however the second one uses a complex vector. where it maps the first values together and the second values together. In these simple cases I like the first version much beter. When I run into a reason to use the second one, I'll share.

Back on Track

(defmacro if-let
  "bindings => binding-form test

  If test is true, evaluates then with binding-form bound to the value of 
  test, if not, yields else"
  {:added "1.0"}
  ([bindings then]
   `(if-let ~bindings ~then nil))
  ([bindings then else & oldform]
   (assert-args if-let
     (and (vector? bindings) (nil? oldform)) "a vector for its binding"
     (= 2 (count bindings)) "exactly 2 forms in binding vector")
   (let [form (bindings 0) tst (bindings 1)]
     `(let [temp# ~tst]
        (if temp#
          (let [~form temp#]
            ~then)
          ~else)))))

The first thing I see that I don't know what it is, is the (assert-args) call. I can make some guesses, but I have a few so I figure its a good one to look up to make sure. After hitting the google, I quickly find out that it's a private function and not an openly accessible one, I won't be calling it with my code. But it's still good to understand for the sake of this exercise. Looking at the source for this one, I see that is runs through the arguments of the function and makes sure that the correct number of arguments were passed in based on what the function want. Seeing that I feel silly as the function was named pretty well and that could have just been implied.

  ([bindings then]
   `(if-let ~bindings ~then nil))

The next part I start looking at is the one above this. Having no idea what's going on here with the ` and the ~ symbols, I do some searching online. It turns out that this is a macro and the ~ symbol is replacing those values with the values being passed in. Lets look at this example:

user=>
(let [msg "rawr"] 
  `(println ~msg)
)
(clojure.core/println "rawr")

With my surface understanding of what's going on here, is we are creating a function that we can run at a later point. Seeing as how macros are a big chapter in a book I'm about to get back to, I'm not going to dig in past the surface for now. However our chunk of code in the if-let that we are looking at, creates a macro to call itself again putting the 'bindings' and the 'then' into place with a nil value. Which turns out is the overload call in this function, so we'll move on to that.

(let [form (bindings 0) tst (bindings 1)]
     `(let [temp# ~tst]
        (if temp#
          (let [~form temp#]
            ~then)
          ~else)))))

We see some heavy use of (let) which is ok, we know it's just setting stuff up locally for the function. then we see this guy: [form (bindings 0) tst (bindings 1)]. I do some searching online and read over the function some more then I realize how silly I was. In this function, bindings is being asserted that it's a vector (array), and you can get the value of a vector at an index by calling the vector as a function. So: ([99, 200] 1) returns 200. I attribute my lack of reading this one to the syntax highlighting. In the source, "bindings" and "assert-args" were the same color, making them stand out. "assert-args" was a private function doing stuff under the hood, I assumed "bindings" was also.

After that last puzzle piece, the whole thing becomes readable to me. Call if-let, pass in some bindings and then a then function and let it rip. As long as all the checks pass, it will bind the values and then call the 'then' function passed in.

Lets see if I'm right and try it.

user=> (if-let [is-young true] (println "young")) 
young
nil

user=> (if-let [is-young false] (println "young"))                
nil

Technically I had the right idea, but I was missing part of the idea of what if-let does. The "if-let" function allows us to streamline a "let" block and a nested "if" statement into one cleaner call. So although my code worked, you really want to pass in the actual "then" statement.

user=> (if-let [is-young false] "young" "old")
"old"

user=> (if-let [is-young true] "young" "old") 
"young"

user=> (if-let [is-young true] (println "young") (println "old"))
young
nil

user=> (if-let [is-young false] (println "young") (println "old"))
old
nil

(if-let [is-young true is-old false] (println "young") (println "old"))
java.lang.IllegalArgumentException: if-let requires exactly 2 forms in binding vector (NO_SOURCE_FILE:0)

user=> (if-let [is-young] (println "young") (println "old"))                  
java.lang.IllegalArgumentException: if-let requires exactly 2 forms in binding vector (NO_SOURCE_FILE:0)

The last few calls, I just wanted to see the exceptions we were looking at if we didn't pass in the correct number of arguments for the vector to be formed from. The author of the code went through the trouble to put them in, may as well get some use out of them. :)

Summary

We looked at the (if-let) code, gaining a better understanding of (let) in the process (which makes sense as I was missing the whole point of (if-let) in the first place), touched the surface of macros, gained a passing understanding of the (->) function, saw a way of writing more complex vectors (which I'm not a fan of yet), and found that there is such a thing as private functions in Clojure.

Better understanding Clojure recur

Just playing around with recur more. I really didn't like the example they had online. After digging around some, I got the idea behind recur, it recalls the function it directly sits under. Mostly I see it used in loops in the examples online, however the = function we were looking at yesterday didn't. It was just calling the normal function it was in.

Quick warning, the first couple of examples won't have a way to stop them. I'm running them in repl, and CTRL+C to stop them. I felt that this best explains what recur is doing.

(defn recur-test 
  [message] 
  (println message) 
  (recur message)
)

user=>(recur-test "rawr")
rawr
rawr
rawr
...
(defn recur-test 
  [message count]
  (println (format "%s: %s" message count))
  (recur message (inc count))
)

user=>(recur-test "rawr" 0)
rawr: 0
rawr: 1
rawr: 2
rawr: 3
...

Let's add the if check into the function so we don't have to keep CTRL+C our repl.

(defn recur-test 
  [message count]
  (println (format "%s: %s" message count))
  (if (< count 5)
    (recur message (inc count))
  )
)

user=> (recur-test "rawr" 0)
rawr: 0
rawr: 1
rawr: 2
rawr: 3
rawr: 4
rawr: 5
nil

It becomes pretty apparent what recur is and is doing at this point. Now when we look at the examples on recur in the docs, it makes more sense for those who haven't seen it before: recur docs

Thursday, September 13, 2012

Source-Learning-Closure: Day 2

Previously we looked at the clojure source for the + function and after looking at. Today, we're going to look through the code for the = function.

Clojure: =

Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type independent manner. Clojure's immutable data structures define equals() (and thus =) as a value, not an identity, comparison.

https://github.com/clojure/clojure/blob/1.3.x/src/clj/clojure/core.clj#L718

(defn =
  "Equality. Returns true if x equals y, false if not. Same as
  Java x.equals(y) except it also works for nil, and compares
  numbers and collections in a type-independent manner.  Clojure's immutable data
  structures define equals() (and thus =) as a value, not an identity,
  comparison."
  {:inline (fn [x y] `(. clojure.lang.Util equiv ~x ~y))
   :inline-arities #{2}
   :added "1.0"}
  ([x] true)
  ([x y] (clojure.lang.Util/equiv x y))
  ([x y & more]
   (if (= x y)
     (if (next more)
       (recur y (first more) (next more))
       (= y (first more)))
     false)))

This one starts off pretty simple and much like the last one, so we do some testing with the first couple overloads to see what comes back:

user=> (= 1)
true

user=> (= "")
true

user=> (= nil)
true

The first overload is what you would expect, passing anything into it returns true. I might be looking at this wrong, but this seems kind of pointless.

user=> (= 1 1)
true

user=> (= 1 2)
false

user=> (= 1 "1")
false

user=> (= 1 :1)
false

user=> (= nil nil)
true

No surprises there. And then for the last overload:

([x y & more]
   (if (= x y)
     (if (next more)
       (recur y (first more) (next more))
       (= y (first more)))
     false)))

Off the bat we've got if statements, next/first calls and recur. The if statements are pretty straight forward in Clojure: (if test then else) if check succeeds return value else return other value.

user=> (if true "yes" "no")
"yes"

user=> (if false "yes" (if true "nested yes" "nested no"))
"nested yes"

So we have nested if statements, where either value returned can be a function call, after all functions always return. Next and First are functions to navigate through collections, next gets the next item in the collection, or "more" in this case, where first grabs the first item. Which leaves us with recur. This isn't one I'm familiar with so lets go look it up and see what can be done with it.

The more I searched through the docs, and online resources the more I realized I was assuming recur to be something other than what it is. After digging around a bit, I realized that it wasn't something to be used on it's own. It's purpose is to re-call the function that it's contained in passing in a function to apply before it's next call. The examples online mostly point to loops and such. I then realized I had no idea how to do a loop in Clojure, so I started playing around with that. After much pain I figured out what this example was doing and had a better understanding of loops and recur.

user=> (loop [x 10]
  (when (> x 1)
    (println x)
    (recur (- x 2))))
10
8
6
4
2
nil

So I wanted to put myself to the test. I wanted to create something that wasn't in clojure using a loop & recur. The first thing that jumped into my head was programming's ++ incremental call. But seeing as how that is totally yesterdays math, I want to implement a +++ function! That's right increment by 2, not 1.

As I was digging into it, I realized I had bigger issues...

user=> (defn +++ [val] 
  (loop [i 0] 
    (if (< i 2) (do 
      (+ val 1) 
      (println val)
      (recur (+ i 1))
    ))
  ))
nil
#'user/+++

user=> (+++ 1)
1
1
nil

How was I going to update the parameter passed in, incrementing it and keeping the new value? I tried setting a local variable and updating that, a global variable would probably work but I didn't want to go there, and some random exception throwing syntax goof-rounds. It hit me pretty hard, I've got a lot to learn about Clojure & functional programming in general. So I start looking for other examples online, which eventually led me to a loop that had two sets of values in the loop call: (loop [i 0 j 99]... for example. And in those cases the recur call passed in two functions to apply to the two sets in the loop. That gave me enough to put together a loop that incremented on "i" and updated a value on the second set. Here's what I came up with:

(defn +++ 
  [val] 
  (loop [i 0, return-val val] 
    (if (< i 2) 
      (do 
        (inc return-val) 
        (recur (inc i) (inc return-val))
      )
 
      return-val
    )
  )
)
#'user/+++

user=> (+++ 1)
3

user=> (+++ 99)
101

After a bunch of trial & error, troubleshooting and repl running, I created a +++ incrementing function in Clojure!

Back on Task

([x y & more]
   (if (= x y)
     (if (next more)
       (recur y (first more) (next more))
       (= y (first more)))

So now what do I think the last overload is doing in the = function of Clojure? The syntax is different than the recur & loop blocks I was playing with, but I think that's saying if the first to parameters are equal, continue checking the "more" to make sure they are equal. By which, if there is a "next" item in "more" recur call the whole function ([x y & more]) passing in y to x, the first in "more" and the next of "more" to re-fire off the check. And when it gets to the end, if there aren't any additional values in "more", check the last y we've got against the last (first in a collection of one) value to see if they are equal.

Summary

So, we've looked at the = function, and in tandem most of the other equality functions = == < &rt; and so on, as they were all pretty similar. But what I got from today's digging is that, understand the basics of loops/do/while, and can now read recur logic. We'll at least the simple recur logic I've shown here, it feels like recur has some hidden powers I don't see yet. Oh, and I extended Clojure with the much needed +++ incremental math! :)

The other thing that I'm starting to see, is the difference in functional programming as compared to object-oriented. Up until now, I had only been seeing a completely different syntax, nothing about different thought processes. Now that I'm getting to understand & read Clojure better, I'm starting to but up against the difference in programming thoughts.

Wednesday, September 12, 2012

Source-Learning-Closure: Day 1 (Update)

As I stated in the post about learning the insides of +

Previous post on Clojure +

That there were some odd calls that I didn't understand. +' instead of just + for example. To shed alittle bit of light on it, not all though, I grabbed the code from the wrong function. In the source it's declared twice. Look at the following:

(defn +'
  "Returns the sum of nums. (+) returns 0. Supports arbitrary precision.
  See also: +"
  {:inline (nary-inline 'addP)
   :inline-arities >1?
   :added "1.0"}
  ([] 0)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (addP x y)))
  ([x y & more]
   (reduce1 +' (+' x y) more)))

(defn +
  "Returns the sum of nums. (+) returns 0. Does not auto-promote
  longs, will throw on overflow. See also: +'"
  {:inline (nary-inline 'add 'unchecked_add)
   :inline-arities >1?
   :added "1.2"}
  ([] 0)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (add x y)))
  ([x y & more]
     (reduce1 + (+ x y) more)))

So in my examples and exploring, I was digging around for addP and +' and in that case should have been. The actual function + calls "add" and so on. I still don't know what +' is doing yet, but I bet it has something to do with "Supports arbitrary precision." That's another good google search and/or ask a Clojure guru.

The syntaxhighlighter is going crazy! I'm definitely going to need to update that.

Source-Learning-Clojure: Day 1

For the first post in my learning Clojure by reading it, I'm going to try to keep it as simple as possible. Like I stated before, I'm going to assume you can read the most basic syntax of the language. I also dug up the syntax to start using the syntax highlighter I used to use. Hopefully my code examples won't be as painful now, I'll update the highlighter to use actual clojure highlighting soon.

Clojure: +

Returns the sum of nums. (+) returns 0. Does not auto-promote longs, will throw on overflow. See also: +'

https://github.com/clojure/clojure/blob/1.3.x/src/clj/clojure/core.clj#L919

(defn +
  "Returns the sum of nums. (+) returns 0. Does not auto-promote
  longs, will throw on overflow. See also: +'"
  {:inline (nary-inline 'add 'unchecked_add)
   :inline-arities >1?
   :added "1.2"}
  ([] 0)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (add x y)))
  ([x y & more]
     (reduce1 + (+ x y) more)))

To get the super basics out of the way, we'll look at the description and meta-data real quick and only this one time. Well, unless something weird comes up in one of them along the way.

Description

  "Returns the sum of nums. (+) returns 0. Does not auto-promote
  longs, will throw on overflow. See also: +'"

This information comes up in the documentation and such.

Metadata

  {:inline (nary-inline 'add 'unchecked_add)
   :inline-arities >1?
   :added "1.2"}

This is more information that gets pulled up when using the docs in lein repl and such.

Digging In

Ok, with the noise out of the way one of the first things that jump out at me is that the + function is doing more than one thing. It looks like there's overloading available to us.

  ([] 0)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (add x y)))
  ([x y & more]
     (reduce1 + (+ x y) more)))

So I loaded up leiningen (lein repl) and tried out some super simple overloading.

  (defn rawr 
    ([] (println "rawr"))
    ([message] (println (format "%s. rawr!" message)))
  )

And what do you know what...

user=> (rawr)
rawr
nil

user=> (rawr "Whoa")
Whoa. rawr!
nil

...there's Overloading!

This example also tells me that I should remember that these functions always return something, so I should stop using println for testing purposes and just return what I want displayed.

Moving Along

  ([] 0)

Here we see the first overload of the function. It's parameters is an empty vector (or array coming from other languages) []. I found out earlier that is how you create a function that doesn't require any parameters. So if you call it like: (+), it will return the value of that first overload. Looking at the value returned for this, we can safely say that the default value returned from + is 0. So, I'm going to assume at this moment that 0 is the default int value.

Moving Along

  ([x] (cast Number x))

Here we are looking at the overload for passing in a single value. It's taking in that value and casting it to a number. So what happens if we don't pass in a number?

user=> (+ a)
java.lang.Exception: Unable to resolve symbol: a in this context (NO_SOURCE_FILE:1)

There was a good expectation, it throws an exception. So, what is Number? I don't recall seeing caps-first-letter in any of the clojure examples so far. So my guess is that it's hitting java with that?

user=> Number
java.lang.Number
user=> FakeyFake
java.lang.Exception: Unable to resolve symbol: FakeyFake in this context (NO_SOURCE_FILE:0)

Yup, it's a java class.

Moving Along

  ([x y] (. clojure.lang.Numbers (addP x y)))

Ok, so there's a couple of things in here I don't know. What's addP? clojure.lang.Numbers? (. ? So lots of questions for this one.

user=> addP
java.lang.Exception: Unable to resolve symbol: addP in this context (NO_SOURCE_FILE:0)

user=> (addP 1 2)
java.lang.Exception: Unable to resolve symbol: addP in this context (NO_SOURCE_FILE:22)

user=> (addP 1 2)
java.lang.Exception: Unable to resolve symbol: addP in this context (NO_SOURCE_FILE:28)

user=> (.addP 1 2)        
java.lang.IllegalArgumentException: No matching method found: addP for class java.lang.Integer (NO_SOURCE_FILE:0)

Yup, definitely don't know what's going on here. And I definitely don't know how to call java code yet, another thing to look up when I get a moment. So I do some google searching for clojure addP and find this info about addP in clojure. So, seeing that we have access to addP in clojure.lang.Numbers.

user=> (clojure.lang.Numbers/addP 1 2)
java.lang.IllegalArgumentException: No matching method: addP (NO_SOURCE_FILE:52)

Tried some other ways, and those didn't pan out. That syntax looked like what I was seeing elsewhere on the web so that's the one I included.

If I remember correctly, the (. is a call to java. So I try this stuff:

user=> (. clojure.lang.Numbers)
java.lang.IllegalArgumentException: Malformed member expression, expecting (. target member ...) (NO_SOURCE_FILE:8)

user=> (. clojure.lang.Numbers 1)
java.lang.IllegalArgumentException: Malformed member expression (NO_SOURCE_FILE:9)

user=> (. java.lang.Numbers)     
java.lang.IllegalArgumentException: Malformed member expression, expecting (. target member ...) (NO_SOURCE_FILE:10)

user=> (. java.lang.Numbers 1)
java.lang.ClassNotFoundException: java.lang.Numbers (NO_SOURCE_FILE:11)

user=> (. java.lang.Numbers (+ 1 1))
java.lang.ClassNotFoundException: java.lang.Numbers (NO_SOURCE_FILE:12)

user=> (. java.util.Date)
java.lang.IllegalArgumentException: Malformed member expression, expecting (. target member ...) (NO_SOURCE_FILE:18)

So, I start asking around and get these:

user=> (java.util.Date.)                            
#

user=> (. (java.util.Date.) getTime)                
1347486819531

The "." is calling a method on a java object when it's "(." and it's creating a new java object when it's after the java object "Date.", That makes sense enough to move forward.

  ([x y] (. clojure.lang.Numbers (addP x y)))

If I'm saying this right: Call the method addP on the underlaying clojure/java Numbers, code passing in X & Y, and return that result. If that's correct, I'm going to assume based on it's naming, and the naming/code of the underlaying java code that addP adds two values together.

Moving Along

And finally the last overload of the + function:

  ([x y & more]
    (reduce1 +' (+' x y) more)))

One of the big things that jump out here is that it's calling itself as part of this function overload to perform its tasks. It's calling (+ x y) and it's passing itself "+" into it's reduce function. This seems like pretty standard stuff, but figured it would be worth noting that it's a functional language and that my guess would be you can't call an overload in one that precedes it.

user=> (defn fn-order
  ([] "first")
  ([message] (format "%s and then second" (fn-order)))
)
#'user/fn-order

user=> (fn-order)
"first"

user=> (fn-order "woot")
"first and then second"
user=> (defn fn-order                                      
  ([message] (format "%s and then second" (fn-order)))
  ([] "first")                                        
)           
#'user/fn-order

user=> (fn-order)                                          
"first"

user=> (fn-order "woot")                                   
"first and then second"

The first one fired off as I would have expected it to, however I was surprised to find that declaring them in the other order, everything worked! That's definitely something I'll need to ask one of our Clojure/Functional gurus.

After that, the "& more" jumped out. It's a way to call arguments/parameters optionally. The "&" can take any number of params and assigns them to, in this case "more". Later when you call the optional arg, it has all of the values after the required ones assigned to it. So if you were to call this function with say: 1 2 3 4, then the "more" would be (3 4).

user=> (defn test-optional-args                              
  [x y & more]                                          
  more
)
#'user/test-optional-args

user=> (test-optional-args 1 2 3 4 5 6 7 8 9 10)             
(3 4 5 6 7 8 9 10)

One part of the source that's kind of throwing me off is things like "reduce1". Calling that from repl results in errors, but its in the source. Hopefully that'll make sense the further I get into this. Aside from that, using "reduce" in repl instead sheds some light into what it's doing. for reduce you use as such: (reduce f coll). So, you call reduce, passing in the function you want to apply to the values in the collection and then the collection. It will then go from the first value and apply the function to the second value. Then continue that process over and over until it runs through the collection. Lets look at it in actual code.

user=> (reduce + [1 2])
3

user=> (reduce - [1 2])
-1

user=> (reduce * [1 2])
2

"reduce" also has an overload: (reduce f val coll). Where the f is the funciton and coll is collection, val is a value to add to apply before beginning the walk through of the collection. In our "+" functions case: (+ x y). So, for this overload we are adding X & Y, and then adding all of the other values passed into the optional args.

Another thing that doesn't work for me is the "+'" calls in the source. I'll show you an example. I'm beginning to think I've missed something somewhere. The only difference is not including the ', then in repl all is good.

user=(defn test+ ([x y & more] (reduce +' (+' x y) more)))  
#'user/test+

user=> (test+ 1 2 3 4)                                      
java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to java.lang.Number (NO_SOURCE_FILE:0)

user=> (defn test+ ([x y & more] (reduce + (+ x y) more)))  
#'user/test+

user=> (test+ 1 2 3 4)                                    
10

Experiment

When I wrote the "test+" function to work through reduce, I realized that, even though I was reading the source code that showed the example, that + was declared in the code as the function name. Looks like there aren't any and/or few restricted values that names can be. So I wanted to test this out a little:

user=> (defn TK-421 [] "Why aren't you at your post?")
#'user/TK-421

user=> (TK-421)                                       
"Why aren't you at your post?"

Ha, now that's a function! But what happens if I override a function that already exists? Say the + function:

user=> (defn + [] "rawr")
WARNING: + already refers to: #'clojure.core/+ in namespace: user, being replaced by: #'user/+
#'user/+

user=> (+)
"rawr"

user=> (+ 1)
java.lang.IllegalArgumentException: Wrong number of args (1) passed to: user$-PLUS- (NO_SOURCE_FILE:0)

user=> (+ 1 2)
java.lang.IllegalArgumentException: Wrong number of args (2) passed to: user$-PLUS- (NO_SOURCE_FILE:0)

So, we overrode the + function, which overwrote all of its overloads. Or better said: Our awesome override, overrode, the old overloads...

Summary

Day 1 in the source and I've learned that we have; Overloading in Clojure, Overloading can call its other overload methods even if they were declared afterwards, Reinforced that functions always return, reinforced that we can create parameterless & optional parameter functions, that "." is (so far) used to call the underlaying java code, Reduce takes a function and a collection and then applies the function to all of the values in the collection, that the source is written slightly differently than the repl expects Clojure to be written, that you can override the already existing functions, and that I'm going to assume for now that naming has little to no restrictions.

Learning Clojure: needing a different approach.

I'm having issues with learning Clojure. I'm picking up bits and parts, but the more I read online and in the books the more I find stuff that isn't sinking in. On top of that the tabs in my browser exploded with blog posts, articles, examples, and so on. It's time to try learning clojure a different way; by digging through the source.

I'm going to start off as small as possible, and see where it leads. I'll post as much as I can about it in the hopes of sounding like I don't know what I'm talking about and someone out there correcting me. I'll need to make the assumption that one can read the basic Clojure syntax, but not much beyond that.

I'm going to use these as my resources, unless I find or am given something better.

http://clojure.org/cheatsheet

http://clojuredocs.org/clojure_core

https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj

If you're interested in the future posts about this, I'll tag them all with source-learning-clojure.

Tuesday, September 11, 2012

Clojure Start

Started in Clojure a couple of nights ago, getting familiar with the language, syntax and functional programming in general. This one is definitely going to test me. I've read through a few online resources and made decent head way on a few of the Clojure books, however something in the language seems to be evading me. I haven't spent this much time in a language and still had, what seems to be pretty standard stuff for the language, be un-readable to me.

Shared learning

So I started bugging the others at work as they had just gone through what I'm starting into. I'm glad they going through the same things, they were able to get me past a few of my current hang-ups.

I'm also going to pair-program in Clojure with a fellow apprentice (Adam) in the mornings. It'll help me with Clojure, and both of us with pairing.

Repo

https://github.com/joeyshipley/game-clojure-simple-rpg

We're going to pair and write a really simple rpg. The focus is to get a better understanding of how to test and what can be tested in Clojure.