Monday, June 27, 2011

Case insensitivity

My first programming experience was with VB.NET in Visual Studio. The IDE would automatically correct case for me, so I was saved from worrying about case until much later in my programming experience.

I am glad that to IDE did this for me. Case is akin to syntax highlighting, it is a way of presenting code graphically, so it should be controlled by the IDE. Here are more reasons for this:

1. English is case insensitive.
2. It can be cumbersome to click shift.
3. There is no good way of presenting case through sound.
4. There are numerous contradictory case conventions, for example Java uses upper camel case for methods and C# uses upper camel case. Clearly case is a personal preference, so it should just be decided by the IDE.

If there is any central tenet of Lisp it is that data and presentation should be separate. This also applies to case as it is just a way of presenting letters graphically.

Common Lisp is case insensitive by default, however, Clojure isn't. Clojure chooses to have case sensitivity, not necessarily because it is a good thing, but rather because it is an absolutely necessary to interoperate with the modern C-based computing world.

Tuesday, June 21, 2011

Nested upto

A simple upto function might look like this:

(defn upto
  "Get the numbers from 1 to n."
  [n]

  (range 1 (inc n)))

This can be extended to a nested upto function:

(defn nested-upto
  "Compute the numbers upto n nested by k."
  [n k]

  (cond
   (= k 0) 1
   (= k 1) n   
   :else (map #(nested-upto % (dec k)) (range 1 (inc n)))))

Here is upto 5 at different levels of nesting to show what I mean:

(1 2 3 4 5)

((1) (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5))

(((1))
 ((1) (1 2))
 ((1) (1 2) (1 2 3))
 ((1) (1 2) (1 2 3) (1 2 3 4))
 ((1) (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5)))

The multichoose function I talked about previously can now be implemented using nested ranges:

(defn multichoose
  [n k]
  (apply + (flatten (list (nested-upto n k)))))

This demonstrates this basic mathematical principle.

Saturday, June 18, 2011

List processing functions continued

I am going to implement all of the array methods from the JavaScript prelude. First of all here is the mutator methods:

(swap! coll rest)                 ; shift
(swap! coll butlast)              ; pop
(swap! coll concat [1])           ; push
(swap! coll (partial concat [1])) ; unshift

(swap! coll reverse) 
(swap! coll (partial sort <))
The only one that really requires special attention is splice.
(defn splice
  [coll start-index how-many & insertions]

  (let [start-coll (map coll (range 0 start-index))
        end-coll (map coll (range (+ start-index how-many) (count coll)))]
    (concat start-coll insertions end-coll)))
The accessor method concat is already implemented in Clojure, and here is the rest of the methods:
(defn join
  [coll separator]

  (cond
   (empty? coll) ""
   (= (count coll) 1) (str (first coll))
   :else (str (first coll) separator (join (rest coll) separator))))

(defn to-string
  [coll]

  (join coll ","))

(defn to-source
  [coll]
  
  (str "[" (join coll ", ") "]"))

(defn slice
  [coll start end]

  (map coll (range start end)))

(defn index-of
  [coll elt]

  (cond
   (nil? ((set coll) elt)) -1
   (= (first coll) elt) 0
   :else (inc (index-of (rest coll) elt))))

(defn last-index-of
  [coll elt]

  (- (dec (count coll)) (index-of (reverse coll) elt)))

The methods, filter, map, some, every?, and reduce are already implemented in clojure. The only thing we don't really have already is for-each. This can be implemented as a macro that uses the loop primitive.
(defmacro for-each
  [coll func]

  (let [i (gensym)]
    `(loop [~i 0]
       (when-not (= ~i (count ~coll))
         (do
           (~func (nth ~coll ~i))
           (recur (inc ~i)))))))
This function is actually quite useful, for example we can use it print out elements of a list:
(for-each [1 2 3 4 5] prn)

Wednesday, June 15, 2011

List processing functions push, pop, shift, unshift

In Clojure most funtions are purely functional, and side effects occur by applying pure functions to objects. So instead of the shift and pop functions, we have rest and butlast:

(swap! coll rest)
(swap! coll butlast)

We can also take a slice over the collection by mapping over a range:

(swap! coll map (range 0 2))

Adding new elements to the collection like with unshift and push is a bit more complicated. You can use conj to add new elements to a list depending on rather it is a list or a vector, however, that is not neccessarily the same thing as push and unshift, so instead we should use concat:

(swap! coll concat [1 2 3])

Unshift is the hardest to implement yet:

(defn unshift 
  "Add the elements of the first collections behind the later ones." 
  [& colls]

  (apply concat (reverse colls)))

(swap! coll ushift [1 2 3])

Now we can do these familiar array operations in Clojure. I think this shows that the application of pure functions - which is the fundemental basis of Clojure's effect system - is a legitimate and powerful model of computation.

Due to the advantages of purity, we should limit our impure functions to a minimum. What few impure functions we do have should be distinguished with an exclamation mark, like the swap! function.

Saturday, June 11, 2011

Implementing get-in

This is an implementation of matrix point access:

(defn curried-apply*
  "Apply args to the curried function func."
  [func args]

  (if (= (count args) 1)
    (func (first args))
    (curried-apply* (func (first args)) (rest args))))

(defn decurrify
  "Take a curried function and return an uncurried function."
  [func]

  (fn [& args]
    (curried-apply* func args)))

(defn get-in*
  "Get the value of the matrix at a point."
  [matrix point]

  (apply (decurrify matrix) point))

This really demonstrates the power of functional programming. The function to decurrify a matrix can also be used to get the value at a point, since a matrix is actually just a curried function.

Friday, June 10, 2011

Programming Clojure

Now I am going through the programming Clojure book. It provides many useful insights about the language.

Tuesday, June 7, 2011

Dvorak

For years I was a qwerty typist, and I used Algol-based languages such as C, Perl, and JavaScript, which benefit from the position of the punctuation keys on qwerty. Now, I have discovered a superior keyboard layout: dvorak.


The most important letters are placed on the home row and all of the other letters are placed in accessible positions. This makes typing English much easier, which is especially helpful when typing lisp, as lisp is essentially english words structured with parenthesis.

Dvorak moves the dash symbol to the home row which is a big boost to lispers, as we use the dash as our separator, on the other hand it is only used for subtraction in most programming languages.

The semicolon is moved off of the homerow to the inaccessible position below the left pinky. The other brackets are also moved further away. This is fine for lispers, the parenthesis are what matter anyways.