Monday, 16 January 2017

SICP in Clojure: Chapter 2 (part 1)

Going on with my study of SICP, this is the first part of chapter 2 (that is a very big chapter and also has a lot of great examples). I also updated the code in the first chapter for some issues with chapter 2 names that were replicated (I made some private definitions there to use refer all here).
The painter example of this book was really cool and actually you can create a painter with Quil library if you want to see it works.

(ns sicp.chapter-2
  (:require [sicp.chapter-1 :refer :all]))

;Common functions
(defn null? [l] (and (seq? l) (empty? l)))
;Chapther 2: Building Abstractions with Data
(defn linear-combination [a b x y]
  (+ (* a x) (* b y)))
(declare add mul)
(defn linear-combination [a b x y]
  (add (mul a x) (mul b y)))

;Chapter 2.1.1
(declare make-rat numer denom)
(defn add-rat [x y]
  (make-rat (+ (* (numer x) (denom y))
               (* (numer y) (denom x)))
            (* (denom x) (denom y))))
(defn sub-rat [x y]
  (make-rat (- (* (numer x) (denom y))
               (* (numer y) (denom x)))
            (* (denom x) (denom y))))
(defn mul-rat [x y]
  (make-rat (* (numer x) (numer y))
            (* (denom x) (denom y))))
(defn div-rat [x y]
  (make-rat (* (numer x) (denom y))
            (* (denom x) (numer y))))
(defn equal-rat? [x y]
  (= (* (numer x) (denom y))
     (* (numer y) (denom x))))
(def x (cons 1 [2]))
(first x)
(second x)
(def x (cons 1 [2]))
(def y (cons 3 [4]))
(def z (cons x (cons y [])))
(first (first z))
(first (second z))
(defn make-rat [x y] (cons x [y]))
(def numer first)
(def denom second)
(defn print-rat [x]
  (println "")
  (println (str (numer x) "/" (denom x))))
(def one-half (make-rat 1 2))
(print-rat one-half)
(def one-third (make-rat 1 3))
(print-rat (add-rat one-half one-third))
(print-rat (mul-rat one-half one-third))
(print-rat (add-rat one-third one-third))
(defn make-rat [n d]
  (let [g (gcd n d)]
    (cons (/ n g) [(/ d g)])))

(print-rat (add-rat one-third one-third))
(defn make-rat [n d]
  (cons n [d]))
(defn numer [x]
  (let [g (gcd (first x) (second x))]
    (/ (first x) g)))
(defn denom [x]
  (let [g (gcd (first x) (second x))]
    (/ (second x) g)))
(print-rat (add-rat one-third one-third))
(defn cons [x y]
  (letfn [(dispatch [m]
            (cond (= m 0) x
                  (= m 1) y
                  :else (println "Argument not 0 or 1: CONS" m)))]
    dispatch))
(defn car [z] (z 0))
(defn cdr [z] (z 1))

;Exercise 2.4
(defn cons [x y]
  #(% x y))
(defn car [z]
  (z (fn [p q] p)))

(defn cdr [z]
  (z (fn [p q] q)))

;Exercise 2.6
(def zero (fn [f] (fn [x] x)))
(defn add-1 [n]
  (fn [f] (fn [x] (f (n f) x))))

;Chapters 2.1.4
(declare make-interval lower-bound upper-bound)
(defn add-interval [x y]
  (make-interval (+ (lower-bound x) (lower-bound y))
                 (+ (upper-bound x) (upper-bound y))))
(defn mul-interval [x y]
  (let [p1 (* (lower-bound x) (lower-bound y))
        p2 (* (lower-bound x) (upper-bound y))
        p3 (* (upper-bound x) (lower-bound y))
        p4 (* (upper-bound x) (upper-bound y))]
    (make-interval (min p1 p2 p3 p4)
                   (max p1 p2 p3 p4))))
(defn div-interval [x y]
  (mul-interval
   x
   (make-interval (/ 1.0 (upper-bound y))
                  (/ 1.0 (lower-bound y)))))

;Exercise 2.7
(defn make-interval [a b]
  (cons a [b]))
(defn upper-bound [x] (first x))
(defn lower-bound [x] (second x))

;Exercise 2.11
(defn make-center-width [c w]
  (make-interval (- c w) (+ c w)))
(defn center [i]
  (/ (+ (lower-bound i) (upper-bound i)) 2))
(defn width [i]
  (/ (- (upper-bound i) (lower-bound i)) 2))

;Exercise 2.13
(defn par1 [r1 r2]
  (div-interval (mul-interval r1 r2)
                (add-interval r1 r2)))
(defn par2 [r1 r2]
  (let [one (make-interval 1 1)]
    (div-interval
     one (add-interval (div-interval one r1)
                       (div-interval one r2)))))

;Chapter 2.2.1
(def cons clojure.core/cons)
(cons 1
      (cons 2
            (cons 3
                  (cons 4 nil))))
(list 1 2 3 4)
(def one-through-four (list 1 2 3 4))
(first one-through-four) ;first instead of car
(rest one-through-four)  ;rest instead of car
(first (rest one-through-four))
(cons 10 one-through-four)
(cons 5 one-through-four)

;List Operations
(defn list-ref [items n]
  (if (= n 0)
    (first items)
    (list-ref (rest items) (- n 1))))
(def squares (list 1 4 9 16 25))
(list-ref squares 3)
(defn length [items]
  (if (empty? items)
    0
    (+ 1 (length (rest items)))))
(def odds (list 1 3 5 7))
(length odds)
(defn length [items]
  (letfn [(length-iter [a count]
            (if (empty? a)
              count
              (length-iter (rest a) (+ 1 count))))]
    (length-iter items 0)))
(defn append [list1 list2]
  (if (empty? list1)
    list2
    (cons (first list1) (append (rest list1) list2))))
(append squares odds)
(append odds squares)

;Exercise 2.19
(def us-coins (list 50 25 10 5 1))
(def uk-coins (list 100 50 20 10 5 2 1 0.5))
(declare no-more? except-first-denomination)
(defn cc2-19 [amount coin-values]
  (cond (= amount 0) 1
        (or (< amount 0) (no-more? coin-values)) 0
        :else
        (+ (cc amount
               (except-first-denomination coin-values))
           (cc (- amount
                  (first-denomination coin-values))
               coin-values))))

;Exercise 2.20
(comment  (defn fn-name [ & <parameters>] <body>)
          (def f (fn [x y & z] <body>))
          (def g (fn [& w] <body>)))

;Mapping over a list
(defn scale-list [items factor]
  (if (empty? items)
    nil
    (cons (* (first items) factor)
          (scale-list (rest items) factor))))
(scale-list (list 1 2 3 4 5) 10)

(defn map-ex [proc items]
  (if (empty? items)
    nil
    (cons (proc (first items))
          (map-ex proc (rest items)))))
(map-ex abs (list -10 2.5 -11.6 17))
(map #(* % %) (list 1 2 3 4))
(defn scale-list [items factor]
  (map #(* % factor) items))
;Exercise 2.21
(declare <??>)
(defn square-list [items]
  (if (empty? items)
    nil
    (cons <??> <??>)))
(defn square-list [items]
  (map <??> <??>))

;Exercise 2.22
(defn square-list [items]
  (letfn [(iter [things answer]
            (if (empty? things)
              answer
              (iter (rest things)
                    (concat (square (rest things))
                            answer))))]
    (iter items nil)))
(defn square-list [items]
  (letfn [(iter [things answer]
            (if (empty? things)
              answer
              (iter (rest things)
                    (cons answer
                          (concat (rest things))))))]
    (iter items nil)))

;Exercise 2.23
(def for-each map)
(for-each (fn [x]
            (println "")
            (println x))
          (list 57 321 88))

;Chapter 2.2.2
(defn count-leaves [x]
  (cond (and (seq? x) (empty? x)) 0
        ((complement seq?) x) 1
        :else (+ (count-leaves (first x))
                 (count-leaves (rest x)))))
(cons (list 1 2) (list 3 4))
(def x (cons (list 1 2) (list 3 4)))
(length x)
(count-leaves x)
(list x x)
(length (list x x))
(count-leaves (list x x))

;Exercise 2.26
(def x (list 1 2 3))
(def y (list 4 5 6))
(append x y)
(cons x y)
(list x y)

;Exercise 2.27
(def x (list (list 1 2) (list 3 4)))
x
(reverse x)
(comment  (deep-reverse x))

;Exercise 2.29
(defn make-mobile [left right]
  (list left right))
(defn make-branch [length structure]
  (list length structure))

;Mapping over trees
(defn scale-tree [tree factor]
  (cond (null? tree) nil
        ((complement seq?) tree) (* tree factor)
        :else (cons (scale-tree (first tree) factor)
                    (scale-tree (rest tree)  factor))))
(scale-tree (list 1 (list 2 (list 3 4) 5) (list 6 7)) 10)
(defn scale-tree [tree factor]
  (map (fn [sub-tree]
         (if (seq? sub-tree)
           (scale-tree sub-tree factor)
           (* sub-tree factor)))
       tree))

;Exercise 2.31
(declare tree-map)
(defn square-tree [tree] (tree-map square tree))

;Exercise 2.32
(defn subsets [s]
  (if (null? s)
    (list nil)
    (let [rest (subsets (rest s))]
      (concat rest (map <??> rest)))))

;Chapter 2.2.3
(defn sum-odd-squares [tree]
  (cond (null? tree) 0
        (not (seq? tree)) (if (odd? tree)
                            (square tree)
                            0)
        :else (+ (sum-odd-squares (first tree))
                 (sum-odd-squares (rest tree)))))
(defn even-fibs [n]
  (letfn [(next [k]
            (if (> k n)
              nil
              (let [f (fib k)]
                (if (even? f)
                  (cons f (next (+ k 1)))
                  (next (+ k 1))))))]
    (next 0)))

;Sequence Operations
(map square (list 1 2 3 4 5))
(defn filter [predicate sequence]
  (cond (null? sequence) nil
        (predicate (first sequence)) (cons (first sequence)
                                           (filter predicate (rest sequence)))
        :else (filter predicate (rest sequence))))
(filter odd? (list 1 2 3 4 5))
(defn accumulate [op initial sequence]
  (if (null? sequence)
    initial
    (op (first sequence)
        (accumulate op initial (rest sequence)))))
(accumulate + 0 (list 1 2 3 4 5))
(accumulate * 1 (list 1 2 3 4 5))
(accumulate cons nil (list 1 2 3 4 5))
(defn enumerate-interval [low high]
  (if (> low high)
    nil
    (cons low (enumerate-interval (+ low 1) high))))
(enumerate-interval 2 7)
(defn enumerate-tree [tree]
  (cond (null? tree) nil
        (not (seq? tree)) (list tree)
        :else (concat (enumerate-tree (first tree))
                      (enumerate-tree (rest tree)))))
(enumerate-tree (list 1 (list 2 (list 3 4)) 5))
(defn sum-odd-squares [tree]
  (accumulate
   + 0 (map square (filter odd? (enumerate-tree tree)))))
(defn even-fibs [n]
  (accumulate
   cons nil (filter even? (map fib (enumerate-interval 0 n)))))
(defn list-fib-squares [n]
  (accumulate
   cons nil (map square (map fib (enumerate-interval 0 n)))))
(list-fib-squares 10)
(defn product-of-squares-of-odd-elements [sequence]
  (accumulate * 1 (map square (filter odd? sequence))))
(product-of-squares-of-odd-elements (list 1 2 3 4 5))
(letfn [(salary [] <??>)
        (programmer? [] <??>)]
  (defn salary-of-highest-paid-programmer [records]
    (accumulate max 0 (map salary (filter programmer? records)))))

;Exercise 2.23
(defn map-2.23 [p sequence]
  (accumulate (fn [x y] <??> nil sequence)))
(defn append-2.23 [seq1 seq2]
  (accumulate cons <??> <??>))
(defn length-2.23 [sequence]
  (accumulate <??> 0 sequence))

;Exercise 2.34
(defn horner-eval [x coefficient-sequence]
  (accumulate (fn [this-coeff higher-term] <??>)
              0
              coefficient-sequence))

;Exercise 2.35
(defn count-leaves-2.35 [t]
  (accumulate <??> <??> (map <??> <??>)))

;Exercise 2.36
(defn accumulate-n [op init seqs]
  (if (null? (first seqs))
    nil
    (cons (accumulate op init <??>)
          (accumulate-n op init <??>))))

;Exercise 2.37
(defn dot-product [v w]
  (accumulate + 0 (map * v w)))
(defn matrix-*-vector [m v]
  (map <??> m))
(defn transpose [mat]
  (accumulate-n <??> <??> mat))
(defn matrix-*-matrix [m n]
  (let [cols (transpose n)]
    (map <??> m)))

;Exercise 2.38
(def fold-right accumulate)
(defn fold-left [op initial sequence]
  (letfn [(iter [result rest-seq]
            (if (null? rest)
              result
              (iter (op result (first rest-seq))
                    (rest rest-seq))))]
    (iter initial sequence)))
(fold-right / 1 (list 1 2 3))
(try
  (fold-left / 1 (list 1 2 3))
  (catch Exception e))
(fold-right list nil (list 1 2 3))
(try (fold-left list nil (list 1 2 3))
     (catch StackOverflowError e))

;Exercise 2.39
(defn reverse-1 [sequence]
  (fold-right (fn [x y] <??>) nil sequence))
(defn reverse-2 [sequence]
  (fold-left (fn [x y] <??>) nil sequence))

;Nested Mappings
(let [n 4]
  (accumulate
   append nil (map (fn [i]
                     (map (fn [j] (list i j))
                          (enumerate-interval 1 (- i 1))))
                   (enumerate-interval 1 n))))
(defn flatmap [proc seq]
  (accumulate append nil (map proc seq)))
(defn prime-sum? [pair]
  (prime? (+ (first pair) (first (rest pair)))))
(defn make-pair-sum [pair]
  (list (first pair) (first (rest pair)) (+ (first pair) (first (rest pair)))))
(defn prime-sum-pairs [n]
  (map make-pair-sum
       (filter prime-sum? (flatmap
                           (fn [i]
                             (map (fn [j] (list i j))
                                  (enumerate-interval 1 (- i 1))))
                           (enumerate-interval 1 n)))))
(defn permutations [s]
  (letfn [(remove [item sequence]
            (filter (fn [x] (not (= x item))) sequence))]
    (if (null? s)
      (list nil)
      (flatmap (fn [x]
                 (map (fn [p] (cons x p))
                      (permutations (remove x s))))
               s))))

;Exercise 2.42
(letfn [(empty-board [] <??>)
        (safe? [] <??>)
        (adjoin-position [] <??>)]
  (defn queens [board-size]
    (letfn [(queen-cols [k]
              (if (= k 0)
                (list empty-board)
                (filter
                 (fn [positions] (safe? k positions))
                 (flatmap
                  (fn [rest-of-queens]
                    (map (fn [new-row]
                           (adjoin-position
                            new-row k rest-of-queens))
                         (enumerate-interval 1 board-size)))
                  (queen-cols (- k 1))))))]
      (queen-cols board-size))))

;Exercise 2.43
(comment
  (flatmap
   (fn [new-row]
     (map (fn [rest-of-queens]
            (adjoin-position new-row k rest-of-queens))
          (queen-cols (- k 1))))
   (enumerate-interval 1 board-size)))

;Chapter 2.2.4 A Picture Language
(declare wave beside flip-vert flip-horiz below up-split corner-split
         sub-vect make-vect add-vect origin-frame draw-line start-segment
         end-segment)
(defn flipped-pairs [painter]
  (let [painter2 (beside painter (flip-vert painter))]
    (below painter2 painter2)))
(comment
  (def wave2 (beside wave (flip-vert wave)))
  (def wave4 (below wave2 wave2))
  (def wave4 (flipped-pairs wave)))
(defn right-split [painter n]
  (if (= n 0)
    painter
    (let [smaller (right-split painter (- n 1))]
      (beside painter (below smaller smaller)))))
(defn up-split [painter n]
  (if (= n 0)
    painter
    (let [smaller (up-split painter (- n 1))]
      (below painter (beside smaller smaller)))))
(defn corner-split [painter n]
  (if (= n 0)
    painter
    (let [up (up-split painter (- n 1))
          right (right-split painter (- n 1))]
      (let [top-left (beside up up)
            bottom-right (below right right)
            corner (corner-split painter (- n 1))]
        (beside (below painter top-left)
                (below bottom-right corner))))))
(defn square-limit [painter n]
  (let [quarter (corner-split painter n)]
    (let [half (beside (flip-horiz quarter) quarter)]
      (below (flip-vert half half)))))
(defn square-of-four [tl tr bl br]
  (fn [painter]
    (let [top (beside (tl painter) (tr painter))
          bottom (beside (bl painter) (br painter))]
      (below bottom top))))
(defn flipped-pairs [painter]
  (let [combine4 (square-of-four identity flip-vert
                                 identity flip-vert)]
    (combine4 painter)))
(def rotate180 (comp flip-vert flip-horiz))
(defn square-limit [painter n]
  (let [combine4 (square-of-four flip-horiz identity
                                 rotate180 flip-vert)]))
(defn frame-coord-map [frame]
  (fn [v]
    (add-vect
     (origin-frame frame))))

;Exercise 2.47
(defn make-frame [origin edge1 edge2]
  (list origin edge1 edge2))

;Painters
(defn segments->painter [segment-list]
  (fn [frame]
    (for-each (fn [segment]
                (draw-line
                 ((frame-coord-map frame)
                  (start-segment segment))
                 ((frame-coord-map frame)
                  (end-segment segment))))
              segment-list)))
;Transforming and combining painters
(defn transform-painter [painter origin corner1 corner2]
  (fn [frame]
    (let [m (frame-coord-map frame)]
      (let [new-origin (m origin)]
        (painter (make-frame
                  new-origin
                  (sub-vect (m corner1) new-origin)
                  (sub-vect (m corner2) new-origin)))))))
(defn flip-vert [painter]
  (transform-painter painter
                     (make-vect 0.0 1.0)
                     (make-vect 1.0 1.0)
                     (make-vect 0.0 0.0)))
(defn shrink-to-upper-right [painter]
  (transform-painter
   painter (make-vect 0.5 0.5)
   (make-vect 1.0 0.5) (make-vect 0.5 1.0)))
(defn rotate80 [painter]
  (transform-painter painter
                     (make-vect 1.0 0.0)
                     (make-vect 1.0 1.0)
                     (make-vect 0.0 0.0)))
(defn squash-inwards [painter]
  (transform-painter painter
                     (make-vect 0.0 0.0)
                     (make-vect 0.65 0.35)
                     (make-vect 0.35 0.65)))
(defn beside [painter1 painter2]
  (let [split-point (make-vect 0.5 0.0)]
    (let [paint-left
          (transform-painter
           painter1
           (make-vect 0.0 0.0)
           split-point
           (make-vect 0.0 1.0))
          paint-right
          (transform-painter
           painter2
           split-point
           (make-vect 1.0 0.0)
           (make-vect 0.5 1.0))]
      (fn [frame]
        (paint-left frame)
        (paint-right frame)))))

Sunday, 8 January 2017

What Clojure is missing...

Ok, now I have played with Clojure for a lot of time.
I know how to write clojure programs, how to write in a functional style (on a base-medium level).
What is my main work, what kind of applications I build for my company... Web Applications, batch programs for some heavy computations. Our main application is built with Grails, and I can't say that I'm am so found on Grails..... buuut ....
Lately I built a web app to handle the deployment through Docker of our Web Application and I was thinking about using Clojure.
This is how the discussion went (more or less):
Marco: "I would like to use Clojure, is great, it gives immediate feedback and I would like to try because I feel I can do a good job"
Other People (in this company before starting we discuss pro and contro of every decision):
"Mmm I heard of it.. yes it can be an idea, but what are you going to use, what is the standard. Let's say that you start the application and then you have to move on another project, what should we start learning to be able to take over"
Marco: "Well I was thinking of using Luminus, it's quite well documented and it has already been used in production from what I know"
Others: "Ok, how are you going to divide the project? There are conventions like in Grails or Play Framework? You know is easier for new guys to join in a project if there are some standard rules"
Marco: "Mmm no there are some standard rules, I will organize the namespaces in the best way to be readable and easy for people to join in"
etc...

Unfortunately after this sentence I was not able to convince anymore my co-workers... and that's the reason for my post.
Grails, Spring Framework, Play Framework (Scala ..... one of the hardest language I ever studied) are standards that can be used in big companies. People that join the company and start work on the projects feels at home if they have already used them, for example in Grails they know that there will be a Controller, and then a Business Logic or a Model, but more or less they know how things will go, and will have the ability to join in the effort quite fast and without tutoring (or very less tutoring) because the documentation is really huge, and the approach Convention Over Configuration really help in this situation.
Clojure is missing a good framework with Convention Over Configuration, that explain also how to organize namespaces and that "force" developers that use it in a direction that is well documented and that can be easily grasp by new developers that join the project.
I have seen a lot of Clojure applications, and all of them have a very different approach in solving the problem that they face. If I have to start working on any of them, I fear I will need a lot of help to be productive.
It's true, I'm a Clojure and functional programmer Noob. But also when I will be a Pro Clojure programmer, my main concern will be, Clojure Noobs will soon join me, I want to easy their life, I want them to be productive.
I will continue my travel to become a Pro Clojure programmer, with this in mind, I have to create something that will give me the ability to reply to my co-workers:
"Yes this is the standard way to do things and can be easily learn from new people, this is the "Spring" framework of Clojure"
With something that set the standards on how to do Web Applications in Clojure, I'm sure this fantastic language will take more hype and attention in the future.

What is your idea? Have I missed a "De Facto" Standard guideline that explain how to write Web Apps in Clojure using a design model that is universally approved? I hope that the Arachne Framework will fix this issue but until documentation will be available I will not have a clue...

Friday, 6 January 2017

SICP in Clojure: Chapter 1

With a new year some new objectives should be set.

  1. Learn French
  2. Understand better functional programming
  3. Use Clojure in a real project (if you need help in some real project let me know :) )
This post is about the 2nd point. To learn more about functional programming I'm reading Structure and Interpretation of Computer Programs. This is really a great book but all the examples are in Lisp.
To make it more actual I'm rewriting all the examples in clojure (and some exercises too).  
I think it can be useful to others too, so here it is chapter 1:


(ns sicp.chapter-1)

;1.1 Expressions
(+ 137 349)
(- 1000 334)
(* 5 99)
(/ 10 5)
(+ 2.7 10)
(+ 21 35 12 7)
(* 25 4 12)
(+ (* 3 5) (- 10 6))
(+ (* 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6))
(+ (* 3
      (+ (* 2 4)
         (+ 3 5)))
   (+ (- 10 7)
      6))

;1.2 Naming and the Environment
(def size 2)
size
(* 5 size)
(def pi 3.14159)
(def radius 10)
(* pi (* radius radius))
(def circumference (* 2 pi radius))
circumference

;1.1.3 Evaluating Combinations
(* (+ 2 (* 4 6))
   (+ 3 5 7))

;1.1.4 Compound Procedures
(defn square [x] (* x x))

;(defn <name> [<formal parameters>] <body>)
(square 21)
(square (+ 2 5))
(square (square 3))
(defn sum-of-squares
  [x y]
  (+ (square x) (square y)))
(sum-of-squares 3 4)
(defn f [a]
  (sum-of-squares (+ a 1) (* a 2)))
(f 5)

;1.1.5 The Substitution Model for Procedure Applincation
(f 5)
(sum-of-squares (+ 5 1) (* 5 2))
(+ (square 6) (square 10))
(+ 36 100)
(sum-of-squares (+ 5 1) (* 5 2))
(+ (square (+ 5 1)) (square (* 5 2)))
(+ (* (+ 5 1) (+ 5 1)) (* (* 5 2) (* 5 2)))
(+ (* 6 6) (* 10 10))
(+ 36 100)
(defn abs [x]
  (cond (> x 0) x
        (= x 0) 0
        (< x 0 ) (- x)))
(comment
  (cond <p1> <e1>
        <p2> <e2>
        ...
        <pn> <en>
        :else <e>))
(defn abs [x]
  (cond (< x 0) (- x)
        :else x))
(defn abs [x]
  (if (< x 0)
    (- x)
    x))
(comment
  (if <predicate>
    <consequent>
    <alternative>))
(comment
  (and <e1> .... <en>))
(comment
  (or <e1> ... <en>))
(comment
  (not <e>))
(comment (and (> x 5) (< x 10)))
(defn >= [x y]
  (or (> x y) (= x y)))
(defn >= [x y]
  (not (< x y)))
;Exercise 1.1
10
(+ 5 3 4)
(- 9 1)
(/ 6 2)
(+ (* 2 4) (- 4 6))
(def ^:private a 3)
(def ^:private b (+ a 1))
(+ a b (* a b))
(= a b)
(if (and (> b a) (< b (* a b)))
  b
  a)
(cond (= a 4) 6
      (= b 4) (+ 6 7 a)
      :else 25)
(+ 2 (if (> b a) b a))
(* (cond (> a b) a
         (< a b) b
         :else -1)
   (+ a 1))

;Exercise 1.2
(/ (+ 5
      4
      (- 2
         (- 3
            (+ 6
               (/ 4 5)))))
   (* 3
      (- 6 2)
      (- 2 7)))

;Exercise 1.3
(defn ex1-3
  [a b c]
  (cond
    (and (< a b) (< a c)) (+ (square b) (square c))
    (and (< b a) (< b c)) (+ (square a) (square c))
    :else (+ (square a) (square b))))

;Exercise 1.4
(defn a-plus-abs-b
  [a b]
  ((if (> b 0) + -) a b))

;Example 1.1.7
(defn good-enough? [guess x]
  (< (abs (- (square guess) x)) 0.001))
(defn average [x y]
  (/ (+ x y) 2))
(defn improve [guess x]
  (average guess (/ x guess)))
(defn sqrt-iter [guess x]
  (if (good-enough? guess x)
    guess
    (sqrt-iter (improve guess x) x)))
(defn sqrt [x]
  (sqrt-iter 1.0 x))
(sqrt 9)
(sqrt (+ (sqrt 2) (sqrt 3)))
(square (sqrt 1000))

;Exercise 1.6
(defn new-if [predicate then-clause else-clause]
  (cond
    predicate then-clause
    :else else-clause))
(new-if (= 2 3) 0 5)
(new-if (= 1 1) 0 5)
(defn new-sqrt-iter [guess x]
  (new-if (good-enough? guess x)
          guess
          (new-sqrt-iter (improve guess x) x)))
(defn new-sqrt [x]
  (new-sqrt-iter 1.0 x))

; (new-sqrt 9) -> Overflow

;Exercise 1.7
(good-enough?
 1000000000000000000000
 1000000000000000000000)
(good-enough? 1 1)
(defn new-good-enough? [prev-guess new-guess]
  (< (abs (- new-guess prev-guess)) 0.001))
(new-good-enough?
 1000000000000000000000
 1000000000000000000000)
(defn new-sqrt-iter-2 [guess x]
  (if (new-good-enough? guess (improve guess x))
    (improve guess x)
    (new-sqrt-iter-2 (improve guess x) x)))
(defn new-sqrt-2 [x]
  (new-sqrt-iter-2 1.0 x))
(new-sqrt-2 9)

;Exercise 1.8
(defn improve-cube-root [guess x]
  (/
   (+ (/ x (square guess))
      (* 2 guess))
   3))
(defn cube-root-iter [guess x]
  (if (new-good-enough? guess (improve-cube-root guess x))
    (improve-cube-root guess x)
    (cube-root-iter (improve-cube-root guess x) x)))
(defn cube-root [x]
  (cube-root-iter 3.0 x))
(cube-root 27)

;Chapter 1.1.8
(defn square [x] (* x x))
(defn double [x] (+ x x))
(defn square [x] (Math/exp (double (Math/log x))))
(square 3)
(defn sqrt [x]
  (letfn [(good-enough? [guess x]
            (< (abs (- (square guess) x)) 0.001))
          (improve [guess x] (average guess (/ x guess)))
          (sqrt-iter [guess x]
            (if (good-enough? guess x)
              guess
              (sqrt-iter (improve guess x) x)))]
    (sqrt-iter 1.0 x)))
(sqrt 9)
(defn sqrt [x]
  (letfn [(good-enough? [guess]
            (< (abs (- (square guess) x)) 0.001))
          (improve [guess] (average guess (/ x guess)))
          (sqrt-iter [guess]
            (if (good-enough? guess)
              guess
              (sqrt-iter (improve guess))))]
    (sqrt-iter 1.0)))
(sqrt 9)

;Chapter 1.2
(defn factorial [n]
  (if (= n 1)
    1
    (* n (factorial (- n 1)))))
(factorial 6)
(defn factorial [n]
  (letfn [(fact-iter [product counter max-count]
            (if (> counter max-count)
              product
              (fact-iter (* counter product)
                              (+ counter 1)
                              max-count)))]
    (fact-iter 1 1 n)))
(factorial 6)

;Execise 1.9
(letfn [(inc [x] (+ 1 x))
        (dec [x] (- x 1))]
  (defn + [a b]
    (if (= a 0) b (inc (+ (dec a) b))))
  (defn + [a b]
    (if (= a 0) b (+ (dec a) (inc b)))))
(def + clojure.core/+)

;Exercise 1.10
(defn A [x y]
  (cond
    (= y 0) 0
    (= x 0) (* 2 y)
    (= y 1) 2
    :else (A (- x 1) (A x (- y 1)))))
(A 1 10)
(A 2 4)
(A 3 3)
(letfn [(f [n] (A 0 n))
        (g [n] (A 1 n))
        (h [n] (A 2 n))
        (k [n] (* 5 n n))])

;Chapter 1.2.2
(defn fib [n]
  (cond
    (= n 0) 0
    (= n 1) 1
    :else (+ (fib (- n 1))
             (fib (- n 2)))))
(defn fib [n]
  (letfn [(fib-iter [a b count]
            (if (= count 0)
              b
              (fib-iter (+ a b) a (- count 1))))]
    (fib-iter 1 0 n)))
(fib 10)

;Example Counting Change
(defn first-denomination [kind-of-coins]
  (cond
    (= kind-of-coins 1) 1
    (= kind-of-coins 2) 5
    (= kind-of-coins 3) 10
    (= kind-of-coins 4) 25
    (= kind-of-coins 5) 50 ))
(defn cc [amount kind-of-coins]
  (cond
    (= amount 0) 1
    (or (< amount 0) (= kind-of-coins 0)) 0
    :else (+
           (cc amount (- kind-of-coins 1))
           (cc (- amount
                  (first-denomination kind-of-coins))
               kind-of-coins))))
(defn count-change [amount]
  (cc amount 5))
(count-change 100)
(count-change 200)

;Exercise 1.11
(defn f1-11 [n]   ;Recursive
  (if (< n 3)
    n
    (+ (f (- n 1))
       (* 2 (f (- n 2)))
       (* 3 (f (- n 3))))))

;Chapter 1.2.4
(defn expt [b n]
  (if (= n 0)
    1
    (* b (expt b (- n 1)))))
(expt 4 3)
(defn expt [b n]
  (letfn [(expt-iter [b counter product]
            (if (= counter 0)
              product
              (expt-iter b (- counter 1) (* b product))))]
    (expt-iter b n 1)))
(expt 4 3)
(defn fast-expt [b n]
  (cond
    (= n 0) 1
    (even? n) (square (fast-expt b (/ n 2)))
    :else (* b (fast-expt b (- n 1)))))
(fast-expt 4 3)

;Exercise 1.19
(comment
  (defn fib [n]
    (letfn [(fib-iter [a b p q count]
              (cond
                (= count 0) b
                (even? count) (fib-iter a
                                        b
                                        <??>
                                        <??>
                                        (/ count 2))
                :else (fib-iter (+ (* b q) (* a q) (* a p))
                                (+ (* b p) (* a q))
                                p
                                q
                                (- count 1))))])))

;Chapter 1.2.5 Greatest Common Divisors
(defn gcd [a b]
  (if (= b 0)
    a
    (gcd b (rem a b))))

;Chapter 1.2.6 Example: Testing for Primality
(defn smallest-divisor [n]
  (letfn [(divides? [a b]
            (= (rem b a) 0))
          (find-divisor [n test-divisor]
            (cond
              (> (square test-divisor) n) n
              (divides? test-divisor n) test-divisor
              :else (find-divisor n (+ test-divisor 1))))]
    (find-divisor n 2)))
(defn prime? [n]
  (= n (smallest-divisor n)))

;Fermat Test
(defn expmod [base exp m]
  (cond
    (= exp 0) 1
    (even? exp) (rem
                 (square (expmod base (/ exp 2) m))
                 m)
    :else (rem
           (* base (expmod base (- exp 1) m))
           m)))
(defn fermat-test [n]
  (letfn [(try-it [a]
            (= (expmod a n n) a))]
    (try-it (+ 1 (rand (- n 1))))))
(defn fast-prime? [n times]
  (cond
    (= times 0) true
    (fermat-test n) (fast-prime? n (- times 1))
    :else false))

;Exercise 1.21
(smallest-divisor 199)
(smallest-divisor 1999)
(smallest-divisor 19999)

;Exercise 1.22
(defn runtime [] (System/currentTimeMillis))
(defn timed-prime-test [n]
  (letfn [(report-prime [elapsed-time]
            (letfn []
              (println " *** ")
              (println elapsed-time)))
          (start-prime-test [n start-time]
            (if (prime? n)
              (report-prime (- (runtime) start-time))))]
    (println "")
    (println n)
    (start-prime-test n (runtime))))

;Exercise 1.25
(defn expmod [base exp m]
  (rem (fast-expt base exp) m))

;Exercise 1.26
(defn expmod [base exp m]
  (cond
    (= exp 0) 1
    (even? exp) (rem (* (expmod base (/ exp 2) m)
                        (expmod base (/ exp 2) m))
                     m)
    :else
    (rem (* base
            (expmod base (- exp 1) m))
         m)))

;Chapter 1.3
(defn cube [x] (* x x x))

;Chapter 1.3.1
(defn sum-integers [a b]
  (if (> a b)
    0
    (+ a (sum-integers (+ a 1) b))))
(defn sum-cubes [a b]
  (if (> a b)
    0
    (+ (cube a)
       (sum-cubes (+ a 1) b))))
(defn pi-sum [a b]
  (if (> a b)
    0
    (+ (/ 1.0 (* a (+ a 2)))
       (pi-sum (+ a 4) b))))
(defn sum [term a next b]
  (if (> a b)
    0
    (+ (term  a)
       (sum term (next a) next b))))
(defn inc [n] (+ n 1))
(defn sum-cubes [a b]
  (sum cube a inc b))
(sum-cubes 1 100)
(defn sum-integers [a b]
  (letfn [(identity [x] x)]
    (sum identity a inc b)))
(sum-integers 1 5)
(defn pi-sum [a b]
  (letfn [(pi-term [x] (/ 1.0 (* x (+ x 2))))
          (pi-next [x] (+ x 4))]
    (sum pi-term a pi-next b)))
(* 8 (pi-sum 1 1000))
(defn integral [f a b dx]
  (letfn [(add-dx [x] (+ x dx))]
    (* (sum f (+ a (/ dx 2.0)) add-dx b)
       dx)))
(integral cube 0 1 0.01)
(integral cube 0 1 0.001)

;Chapter 1.3.2 Constructing Procedures Using lambda
(fn [x] (+ x 4))
#(+ % 4)
(fn [x] (/ 1.0 (* x (+ x 2))))
#(/ 1.0 (* % (+ % 2)))
(defn pi-sum [a b]
  (sum #(/ 1.0 (* % (+ % 2)))
       a
       #(+ % 4)
       b))
(defn integral [f a b dx]
  (* (sum f
          (+ a (/ dx 2.0))
          #(+ % dx)
          b)
     dx))
(comment  (<fn> [<formal-parameters] <body>) or #(<body> with % as x))
(defn plus4 [x] (+  x 4))
(def plus4 #(+ % 4))
(#(+ %1 %2 (square %3)) 1 2 3)

;Using let to create local variables
(defn f [x y]
  (letfn [(f-helper [a b]
            (+ (* x (square a))
               (* y b)
               (* a b)))]
    (f-helper (+ 1 (* x y))
              (- 1 y))))
(f 1 2)
(defn f [x y]
  ((fn [a b]
     (+ (* x (square a))
               (* y b)
               (* a b)))
   (+ 1 (* x y))
   (- 1 y)))
(f 1 2)
(defn f [x y]
  (let [a (+ 1 (* x y))
        b (- 1 y)]
    (+ (* x (square a))
       (* y b)
       (* a b))))
(f 1 2)
(let [x 5]
  (+ (let [x 3]
       (+ x (* x 10)))
     x))
(let [x 2]
  (let [x 3
        y (+ x 2)]
    (* x y)))
(defn f [x y]
  (let [a (+ 1 (* x y))
        b (- 1 y)]
    (+ (* x (square a))
       (* y b)
       (* a b))))

;Chapter 1.3.3 Procedures as General Methods
(defn close-enough? [x y]
  (< (abs (- x y)) 0.001))
(defn search [f neg-point pos-point]
  (let [midpoint (average neg-point pos-point)]
    (if (close-enough? neg-point pos-point)
      midpoint
      (let [test-value (f midpoint)]
        (cond
          (pos? test-value) (search f neg-point midpoint)
          (neg? test-value) (search f midpoint pos-point)
          :else midpoint)))))
(defn error [s v1 v2]
  (println (str s " " v1 " " v2 )))
(defn half-interval-method [f a b]
  (let [a-value (f a)
        b-value (f b)]
    (cond
      (and (neg? a-value) (pos? b-value)) (search f a b)
      (and (neg? b-value) (pos? a-value)) (search f b a)
      :else (error "Values are not of opposite sign" a b))))
(def sin #(Math/sin %))
(def cos #(Math/cos %))
(half-interval-method sin 2.0 4.0)
(half-interval-method #(- (* % % %) (* 2 %) 3) 1.0 3.0)

;Finding fixed points of functions
(def tolerance 0.00001)
(defn fixed-point [f first-guess]
  (letfn [(close-enough? [v1 v2]
            (< (abs (- v1 v2)) tolerance))
          (try-f [guess]
            (let [next (f guess)]
              (if (close-enough? guess next)
                next
                (try-f next))))]
    (try-f first-guess)))
(fixed-point #(+ (sin %) (cos %)) 1.0)
(defn sqrt [x]
  (fixed-point #(/ x %)
               1.0))
(defn sqrt [x]
  (fixed-point #(average % (/ x %))
               1.0))

;Chapter 1.3.4 Procedures as Returned Values
(defn average-damp [f]
  #(average % (f %)))
((average-damp square) 10)
(defn sqrt [x]
  (fixed-point (average-damp #(/ x %))
               1.0))
(defn cube-root [x]
  (fixed-point (average-damp #(/ x %))
               1.0))
(def dx tolerance)
(defn- deriv [g]
  #(/ (- (g (+ % dx))
         (g %))
      dx))
(defn cube [x] (* x x x))
((deriv cube) 5)
(defn newton-transform [g]
  #(- % (/ (g %) ((deriv g) %))))
(defn newtons-method [g guess]
  (fixed-point (newton-transform g) guess))
(defn sqrt [x]
  (newtons-method
   #(- (square %) x) 1.0))
(defn fixed-point-of-transform [g tranform guess]
  (fixed-point (tranform g) guess))
(defn sqrt [x]
  (fixed-point-of-transform #(/ x %) average-damp 1.0))
(defn sqrt [x]
  (fixed-point-of-transform
   #(- (square %) x) newton-transform 1.0))


Wednesday, 21 January 2015

Light Table

Ok after some work with it I have to say that it's really one of the easiest IDE to start with Clojure.
The auto complete is very well done and is the only ide that make possible to start trying clojure without any issue with the IDE.
ps: if you create a leiningen project LightTable will use the clojure version that you set in it, by default it will instead use the clojure 1.5.1

Monday, 19 January 2015

Clojure Ide: LightTable

Ok it has been some time since I start using clojure.
I have to restart... and what is better than starting with the IDE.
I want to give LightTable a try again, it was interesting last time I tried it.
It's open source (under MIT) and I like the design.
Here the first problems I find, I'm used to projects, so I would like to see a "Start new project" or something like that. Instead in LightTable you don't have that. Actually you don't have either a way to start easily a clojure project....
Ok let's read docs..
"With Clojure...
  1. In the view menu click the commands item (or press Ctrl+Space)
Where is the commands item....., ok I go with the Ctrl+Space, but I don't like when they point me to something that don't exist...
Ok after a little (10 minutes... not so little) I was able to figure out how it works, you create a folder, then you open the folder and it become your workspace.
Actually I would have like a way to create a workspace (also if is a folder), it not so intuitive to open a workspace "folder", just remove the workspace name and I will be happy :D
But ok I have created the first 'workspace' now I will have to refresh my clojure memory. See you soon.

After a while:
Delete file --- double confirm by default.... not user friendly

ps: I will do the cms in a way that people that are reading a post will be able to see if is a 'Real Time post', I like to write while I'm doing things, it helps me  remember things, and this can be interesting if I also have a chat on right where people can ask me for things... I will do that


After another half an hour:
Sorry, LightTable is out, I want to change the clojure version, I can't find a way.
Sorry for that, I like the design but is not user friendly.

15 minutes after:
Installed Leiningen, created a project, opened the folder with LightTable, ok the clojure version is the one I set in the lein project file.... let's go ahead and continue with LightTable (it remains that it's not very user friendly)

Clojure + Clojure Script CMS

Ok after some feedback on my journey I have decided that I will go with a Clojure + Clojure Script site. Stay in touch I will try to do little steps each day to obtain the result. The things I will use to start:
  • Compojure (first I thought ring)
  • Bootstrap
For now I will go with this. I will try the best approach I can think:

Do easy thing first, cover everything with tests, use more tools only when needed

Every comment or help in any post will be accepted with gratitude. I don't think there is a full written history of a new clojurer that try to do something, I hope this will help understand what can be improved in Clojure to help people start using it.
Have a nice evening, post to you soon.

Friday, 16 January 2015

Clojure in a working from home company.

I'm happy to see that some experts are starting reading my blog. This is why I started this in first place. Now I would like to raise a question for anyone that is reading. In normal company is easier to check how people work, help them improve in the way code is written and help them improve as programmers by making in-company seminars and things like that.
Working in a remote company I have the feeling that this is very hard to accomplish. This is why, even though my love for clojure became bigger every day, I feel that static compilation is great when you work on a remote company. For example the biggest problems we have are on our front end, build on groovy. Groovy really is great for front end and thanks to its DSL is also great for database querying.Its dynamic nature help a lot when you need to customize it for clients.
The real issue is that it isn't compiled, this cause often problems because people don't test their code (actually they don't ever navigate in pages they created sometime).
This is why I was investigating on a full stack of technologies that are statically compiled (Scala has also a way to create front-end in a static way, and its Objects can be even more restrictive than Java).
I will start this projects using Angular Js and Clojure-Scala-Java to see which one will be easier for people to mantain and read also from a remote location. What do you think about this? I really would like to listen from people that works every day with Clojure / Scala if they feel that these languages can help also in a distributed 'work' environment.