tag:blogger.com,1999:blog-41976734880008703732018-05-28T03:24:43.459+02:00Clojure Reactive ProgrammingPrinciple of Reactive Programming in ClojureMarco Manzinoreply@blogger.comBlogger20125tag:blogger.com,1999:blog-4197673488000870373.post-62713698243629086892017-03-10T17:06:00.001+01:002017-03-12T23:02:44.640+01:00How to style your input file in Reagent with BootstrapOk this caused me a lot of headache, hope it will help anyone.<br>In bootstrap the only way to style a input with type file, is to close it in a label. Like this:<br><ul class="snippet-no-num" style="box-sizing: border-box; list-style: none; margin: 0px; padding: 0.6em 1em;"><span style="font-family: monaco, consolas, andale mono, dejavu sans mono, monospace;"><span style="font-size: 14px; white-space: pre;"></span></span><li style="box-sizing: border-box; list-style: none; min-height: 22px; padding-left: 0px;"><span style="font-family: monaco, consolas, andale mono, dejavu sans mono, monospace;"><span style="font-size: 14px; white-space: pre;"><label class="btn btn-default btn-file"> Browse <input type="file" style="display: none;"> </label></span></span></li></ul> <a href="http://2.bp.blogspot.com/-5naCwf00Pxs/WMK7OTRUPsI/AAAAAAAAUAU/CFuSeRIHLqUXIRcmmg7XEDSjl3yuchvcwCK4B/s1600/Screenshot%2Bfrom%2B2017-03-10%2B15-41-09.png" imageanchor="1"><img border="0" src="https://2.bp.blogspot.com/-5naCwf00Pxs/WMK7OTRUPsI/AAAAAAAAUAU/CFuSeRIHLqUXIRcmmg7XEDSjl3yuchvcwCK4B/s400/Screenshot%2Bfrom%2B2017-03-10%2B15-41-09.png"></a><br><br>Unfortunately, as things are now, the only way to do something like this in Reagent is to set the InnerHhtml and do something like this:<br><br><pre class="brush: csharp">(defn ^:export on-click<br /> [event]<br /> (js/alert "Upload Button Clicked")<br /><br />(defn ^:export on-change<br /> [event]<br /> (js/alert "File Changed)<br /><br />(def input-html "<input id='upload-file' name='updload-file' type='file' </pre><pre class="brush: csharp">style='display: none;' onclick='{ns}.table.on_click(event)' </pre><pre class="brush: csharp">onchange='{ns}.table.on_change(event);'></input>")<br /></pre><pre class="brush: csharp"></pre><pre class="brush: csharp">[:label.btn.btn-primary.col-span-1<br /> {:dangerouslySetInnerHTML<br /> {:__html (str (label-input "Select File") input-html)}}]<br /><br /><br /></pre>Also the javascript functions that will be called will have to be exported and called using {ns}.function<br>This is the only 'non elegant' solution that is possible now.<br>An interesting thing that give me headache was this one.<br>I wanted to change the label str ("Select File") in the on-change function. I used a reagent atom for that and changed the label in this way:<br><br><pre class="brush: csharp">(def label (reagent/atom "Select File"))<br /><br />(defn ^:export on-change<br /> [event]<br /> (reset! label "New Label)<br /><div><br /></div><br />[:label.btn.btn-primary.col-span-1<br /> {:dangerouslySetInnerHTML<br /> {:__html (str (label-input @label) input-html)}}]<br /><br /><br /></pre>This actually cause the input to loose it's file because React replace the <label> with it's html recreating the input and loosing the file.<br>Hope this will prevent some other guys to have the same headache I had :DMarco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-52925204073695845592017-03-09T22:17:00.000+01:002017-03-10T10:36:07.380+01:00How to do an upload using REST (Swagger) and Clojurescript (ajavHoping to help someone else that is also struggling with this.<br />I have used Luminus with Reagent to try this.<br />Luminus come with Swagger for REST API, it's a great tool because it gives you the possibility to try the API as soon as you have write it.<br />This is the code to write a REST end-point that accept a file in upload<br /><br /><pre class="brush: csharp">(ns your-clojure-ns<br /> (:require [ring.util.http-response :refer :all]<br /> [compojure.api.sweet :refer :all]<br /> [schema.core :as s]<br /> [ring.swagger.upload :as upload])<br /><br />(defapi service-routes<br /> {:swagger {:ui "/swagger-ui"<br /> :spec "/swagger.json"<br /> :data {:info {:version "1.0.0"<br /> :title "Sample API"<br /> :description "Sample Services"}}}}<br /><br /> (context "/your-context" []<br /> :tags ["Your Context"]<br /><br /> (POST "/upload" []<br /> :multipart-params [file :- upload/TempFileUpload]<br /> :middleware [upload/wrap-multipart-params]<br /> (ok (let [{:keys [filename tempfile]} file ]<br /> (do-something-with tempfile)<br /> {:success true}))))<br /><br /><br /><br /></pre>You should already have the right imports in the file created by Luminus, the only one that you have to add is <b>[ring.swagger.upload :as upload] </b>that will give you the Middleware to use for your request.<br />Once you have added this. You should see in your Swagger ui (localhost:3000/swagger-ui) your new API, with the possibility to already send a file to try your logic (<b>do-something-with</b>)<br />Now let's go to the Clojurescript call (that is the hardest part, I lost an evening to figure out the right combination)<br /><br /><pre class="brush: csharp">(ns your-clojurescript-ns<br /> (:require [ajax.core :refer [GET POST]]))<br /><br />(defn upload-file [file]<br /> (letfn [(handle-response-ok [] (js/alert "File Uploaded")<br /> (handle-response-error [] (js/alert "There were problems during the upload"))]<br /> (let [form-data (doto<br /> (js/FormData.)<br /> (.append "file" file))]<br /> (POST "/your-context/upload"<br /> {:body form-data<br /> :response-format :json<br /> :keywords? true<br /> :handler handle-response-ok<br /> :error-handler handle-response-error}))))<br /><br /><br /><br /></pre><b>(.append "file" file)</b> is very important, file is the same name you used in the clojure namespace as parameter, also you have to send the <b>form-data </b>as <b>:body</b>, if you try to send it as a <b>:params </b>(like is written around in internet) you will have an error.<br />Hope this post will be useful.<br /><br /><b>Coming soon... </b>How to style your input with a file using Bootstrap, Reagent and Clojurescript. How changing the label using a Reagent atom can give you some headache.<br /><div><br /></div>Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com1tag:blogger.com,1999:blog-4197673488000870373.post-12836720505267786492017-03-09T15:54:00.001+01:002017-03-10T10:35:54.168+01:00First project with Luminus and Reagent... impressions.Ok I have started a project for a friend https://github.com/marcomanzi/arcatron, it's web application to charge customers for calls done.<br />I'm using Luminus with Reagent as frontend... how it is going...<br />I will compare this with my experience in doing something similar using Java, with Spring and Vaadin. During this development I had more feeling coming out, these are the things I want to share (not ordered by relevance)<br /><br /><ul><li>Fun: Well, this is a totally new experience, I have Terminator with 3 windows, one with lein test-refreh, one with lein run and one with lein figwheel. I really enjoy that I see happening in my browser while I change them. It's a new experience because with Vaadin every little change I had to restart the application server (it does not take long though)</li><li>Creativity: Because there is not a clear path written (with Spring a Vaadin you are taken by hand and they guide you to the final result like a parent with a child) I was able to come out with my solutions for problems, like the creation of a <b><a href="https://github.com/marcomanzi/arcatron/blob/master/src/cljs/arcatron/reagent/table.cljs">paginated-table</a></b> that handle the rendering of a table that automatically resize when the browser window change size.</li><li>Frustration: well also this feeling come out a lot... I'm using swagger to create Rest API, and I'm calling them using <b>ajax.core Get </b>and <b>POST </b>methods. Using a dynamic language is very hard because if you can't find documentation on Internet you are not able to figure how you should use these functions. For example it took me a good evening to make the upload of a file working because I was using the :params key in the POST configuration map instead of the :body, and there was really no feedback to understand that</li><li>Productivity is still very low: Unfortunately the horrible stacktrace of clojure and the error messages make me think that there is still work to do in that direction in clojure to make it more productive.</li></ul><div>Next steps:</div><div><ul><li>Improve my paginated table to make it easier to use, I was not able to encapsulate it fully.</li><li>Move to clojure 1.9 to check if errors are a little more useful</li></ul><div>Wishes:</div></div><div><ul><li>Luminus is a good framework, but still documentation is poor on simple tasks (like doing a full rest application with clojurescript as frontend, lots of common problems (like timeout or security using tokens, ..) don't have a documented solution leaving open the implementation. These are problems that are "old", production tested solution should be documented in the framework and should take less time to set it up.</li></ul><div>If any of you want to go through the code and give me some advice I will gratefully accept that, I feel that I still have to learn a lot on how to write functional programming but I only have my free time to try it :), help from someone is great, also if you have a project where you need some help, let me know.</div></div><div><br /></div><br /><br /><br />Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-9312624450638851902017-01-16T12:21:00.001+01:002017-01-16T12:27:28.060+01:00SICP 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).<br />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.<br /><div><br /></div><div><div><pre class="brush: csharp">(ns sicp.chapter-2<br /> (:require [sicp.chapter-1 :refer :all]))<br /><br />;Common functions<br />(defn null? [l] (and (seq? l) (empty? l)))<br />;Chapther 2: Building Abstractions with Data<br />(defn linear-combination [a b x y]<br /> (+ (* a x) (* b y)))<br />(declare add mul)<br />(defn linear-combination [a b x y]<br /> (add (mul a x) (mul b y)))<br /><br />;Chapter 2.1.1<br />(declare make-rat numer denom)<br />(defn add-rat [x y]<br /> (make-rat (+ (* (numer x) (denom y))<br /> (* (numer y) (denom x)))<br /> (* (denom x) (denom y))))<br />(defn sub-rat [x y]<br /> (make-rat (- (* (numer x) (denom y))<br /> (* (numer y) (denom x)))<br /> (* (denom x) (denom y))))<br />(defn mul-rat [x y]<br /> (make-rat (* (numer x) (numer y))<br /> (* (denom x) (denom y))))<br />(defn div-rat [x y]<br /> (make-rat (* (numer x) (denom y))<br /> (* (denom x) (numer y))))<br />(defn equal-rat? [x y]<br /> (= (* (numer x) (denom y))<br /> (* (numer y) (denom x))))<br />(def x (cons 1 [2]))<br />(first x)<br />(second x)<br />(def x (cons 1 [2]))<br />(def y (cons 3 [4]))<br />(def z (cons x (cons y [])))<br />(first (first z))<br />(first (second z))<br />(defn make-rat [x y] (cons x [y]))<br />(def numer first)<br />(def denom second)<br />(defn print-rat [x]<br /> (println "")<br /> (println (str (numer x) "/" (denom x))))<br />(def one-half (make-rat 1 2))<br />(print-rat one-half)<br />(def one-third (make-rat 1 3))<br />(print-rat (add-rat one-half one-third))<br />(print-rat (mul-rat one-half one-third))<br />(print-rat (add-rat one-third one-third))<br />(defn make-rat [n d]<br /> (let [g (gcd n d)]<br /> (cons (/ n g) [(/ d g)])))<br /><br />(print-rat (add-rat one-third one-third))<br />(defn make-rat [n d]<br /> (cons n [d]))<br />(defn numer [x]<br /> (let [g (gcd (first x) (second x))]<br /> (/ (first x) g)))<br />(defn denom [x]<br /> (let [g (gcd (first x) (second x))]<br /> (/ (second x) g)))<br />(print-rat (add-rat one-third one-third))<br />(defn cons [x y]<br /> (letfn [(dispatch [m]<br /> (cond (= m 0) x<br /> (= m 1) y<br /> :else (println "Argument not 0 or 1: CONS" m)))]<br /> dispatch))<br />(defn car [z] (z 0))<br />(defn cdr [z] (z 1))<br /><br />;Exercise 2.4<br />(defn cons [x y]<br /> #(% x y))<br />(defn car [z]<br /> (z (fn [p q] p)))<br /><br />(defn cdr [z]<br /> (z (fn [p q] q)))<br /><br />;Exercise 2.6<br />(def zero (fn [f] (fn [x] x)))<br />(defn add-1 [n]<br /> (fn [f] (fn [x] (f (n f) x))))<br /><br />;Chapters 2.1.4<br />(declare make-interval lower-bound upper-bound)<br />(defn add-interval [x y]<br /> (make-interval (+ (lower-bound x) (lower-bound y))<br /> (+ (upper-bound x) (upper-bound y))))<br />(defn mul-interval [x y]<br /> (let [p1 (* (lower-bound x) (lower-bound y))<br /> p2 (* (lower-bound x) (upper-bound y))<br /> p3 (* (upper-bound x) (lower-bound y))<br /> p4 (* (upper-bound x) (upper-bound y))]<br /> (make-interval (min p1 p2 p3 p4)<br /> (max p1 p2 p3 p4))))<br />(defn div-interval [x y]<br /> (mul-interval<br /> x<br /> (make-interval (/ 1.0 (upper-bound y))<br /> (/ 1.0 (lower-bound y)))))<br /><br />;Exercise 2.7<br />(defn make-interval [a b]<br /> (cons a [b]))<br />(defn upper-bound [x] (first x))<br />(defn lower-bound [x] (second x))<br /><br />;Exercise 2.11<br />(defn make-center-width [c w]<br /> (make-interval (- c w) (+ c w)))<br />(defn center [i]<br /> (/ (+ (lower-bound i) (upper-bound i)) 2))<br />(defn width [i]<br /> (/ (- (upper-bound i) (lower-bound i)) 2))<br /><br />;Exercise 2.13<br />(defn par1 [r1 r2]<br /> (div-interval (mul-interval r1 r2)<br /> (add-interval r1 r2)))<br />(defn par2 [r1 r2]<br /> (let [one (make-interval 1 1)]<br /> (div-interval<br /> one (add-interval (div-interval one r1)<br /> (div-interval one r2)))))<br /><br />;Chapter 2.2.1<br />(def cons clojure.core/cons)<br />(cons 1<br /> (cons 2<br /> (cons 3<br /> (cons 4 nil))))<br />(list 1 2 3 4)<br />(def one-through-four (list 1 2 3 4))<br />(first one-through-four) ;first instead of car<br />(rest one-through-four) ;rest instead of car<br />(first (rest one-through-four))<br />(cons 10 one-through-four)<br />(cons 5 one-through-four)<br /><br />;List Operations<br />(defn list-ref [items n]<br /> (if (= n 0)<br /> (first items)<br /> (list-ref (rest items) (- n 1))))<br />(def squares (list 1 4 9 16 25))<br />(list-ref squares 3)<br />(defn length [items]<br /> (if (empty? items)<br /> 0<br /> (+ 1 (length (rest items)))))<br />(def odds (list 1 3 5 7))<br />(length odds)<br />(defn length [items]<br /> (letfn [(length-iter [a count]<br /> (if (empty? a)<br /> count<br /> (length-iter (rest a) (+ 1 count))))]<br /> (length-iter items 0)))<br />(defn append [list1 list2]<br /> (if (empty? list1)<br /> list2<br /> (cons (first list1) (append (rest list1) list2))))<br />(append squares odds)<br />(append odds squares)<br /><br />;Exercise 2.19<br />(def us-coins (list 50 25 10 5 1))<br />(def uk-coins (list 100 50 20 10 5 2 1 0.5))<br />(declare no-more? except-first-denomination)<br />(defn cc2-19 [amount coin-values]<br /> (cond (= amount 0) 1<br /> (or (< amount 0) (no-more? coin-values)) 0<br /> :else<br /> (+ (cc amount<br /> (except-first-denomination coin-values))<br /> (cc (- amount<br /> (first-denomination coin-values))<br /> coin-values))))<br /><br />;Exercise 2.20<br />(comment (defn fn-name [ & <parameters>] <body>)<br /> (def f (fn [x y & z] <body>))<br /> (def g (fn [& w] <body>)))<br /><br />;Mapping over a list<br />(defn scale-list [items factor]<br /> (if (empty? items)<br /> nil<br /> (cons (* (first items) factor)<br /> (scale-list (rest items) factor))))<br />(scale-list (list 1 2 3 4 5) 10)<br /><br />(defn map-ex [proc items]<br /> (if (empty? items)<br /> nil<br /> (cons (proc (first items))<br /> (map-ex proc (rest items)))))<br />(map-ex abs (list -10 2.5 -11.6 17))<br />(map #(* % %) (list 1 2 3 4))<br />(defn scale-list [items factor]<br /> (map #(* % factor) items))<br />;Exercise 2.21<br />(declare <??>)<br />(defn square-list [items]<br /> (if (empty? items)<br /> nil<br /> (cons <??> <??>)))<br />(defn square-list [items]<br /> (map <??> <??>))<br /><br />;Exercise 2.22<br />(defn square-list [items]<br /> (letfn [(iter [things answer]<br /> (if (empty? things)<br /> answer<br /> (iter (rest things)<br /> (concat (square (rest things))<br /> answer))))]<br /> (iter items nil)))<br />(defn square-list [items]<br /> (letfn [(iter [things answer]<br /> (if (empty? things)<br /> answer<br /> (iter (rest things)<br /> (cons answer<br /> (concat (rest things))))))]<br /> (iter items nil)))<br /><br />;Exercise 2.23<br />(def for-each map)<br />(for-each (fn [x]<br /> (println "")<br /> (println x))<br /> (list 57 321 88))<br /><br />;Chapter 2.2.2<br />(defn count-leaves [x]<br /> (cond (and (seq? x) (empty? x)) 0<br /> ((complement seq?) x) 1<br /> :else (+ (count-leaves (first x))<br /> (count-leaves (rest x)))))<br />(cons (list 1 2) (list 3 4))<br />(def x (cons (list 1 2) (list 3 4)))<br />(length x)<br />(count-leaves x)<br />(list x x)<br />(length (list x x))<br />(count-leaves (list x x))<br /><br />;Exercise 2.26<br />(def x (list 1 2 3))<br />(def y (list 4 5 6))<br />(append x y)<br />(cons x y)<br />(list x y)<br /><br />;Exercise 2.27<br />(def x (list (list 1 2) (list 3 4)))<br />x<br />(reverse x)<br />(comment (deep-reverse x))<br /><br />;Exercise 2.29<br />(defn make-mobile [left right]<br /> (list left right))<br />(defn make-branch [length structure]<br /> (list length structure))<br /><br />;Mapping over trees<br />(defn scale-tree [tree factor]<br /> (cond (null? tree) nil<br /> ((complement seq?) tree) (* tree factor)<br /> :else (cons (scale-tree (first tree) factor)<br /> (scale-tree (rest tree) factor))))<br />(scale-tree (list 1 (list 2 (list 3 4) 5) (list 6 7)) 10)<br />(defn scale-tree [tree factor]<br /> (map (fn [sub-tree]<br /> (if (seq? sub-tree)<br /> (scale-tree sub-tree factor)<br /> (* sub-tree factor)))<br /> tree))<br /><br />;Exercise 2.31<br />(declare tree-map)<br />(defn square-tree [tree] (tree-map square tree))<br /><br />;Exercise 2.32<br />(defn subsets [s]<br /> (if (null? s)<br /> (list nil)<br /> (let [rest (subsets (rest s))]<br /> (concat rest (map <??> rest)))))<br /><br />;Chapter 2.2.3<br />(defn sum-odd-squares [tree]<br /> (cond (null? tree) 0<br /> (not (seq? tree)) (if (odd? tree)<br /> (square tree)<br /> 0)<br /> :else (+ (sum-odd-squares (first tree))<br /> (sum-odd-squares (rest tree)))))<br />(defn even-fibs [n]<br /> (letfn [(next [k]<br /> (if (> k n)<br /> nil<br /> (let [f (fib k)]<br /> (if (even? f)<br /> (cons f (next (+ k 1)))<br /> (next (+ k 1))))))]<br /> (next 0)))<br /><br />;Sequence Operations<br />(map square (list 1 2 3 4 5))<br />(defn filter [predicate sequence]<br /> (cond (null? sequence) nil<br /> (predicate (first sequence)) (cons (first sequence)<br /> (filter predicate (rest sequence)))<br /> :else (filter predicate (rest sequence))))<br />(filter odd? (list 1 2 3 4 5))<br />(defn accumulate [op initial sequence]<br /> (if (null? sequence)<br /> initial<br /> (op (first sequence)<br /> (accumulate op initial (rest sequence)))))<br />(accumulate + 0 (list 1 2 3 4 5))<br />(accumulate * 1 (list 1 2 3 4 5))<br />(accumulate cons nil (list 1 2 3 4 5))<br />(defn enumerate-interval [low high]<br /> (if (> low high)<br /> nil<br /> (cons low (enumerate-interval (+ low 1) high))))<br />(enumerate-interval 2 7)<br />(defn enumerate-tree [tree]<br /> (cond (null? tree) nil<br /> (not (seq? tree)) (list tree)<br /> :else (concat (enumerate-tree (first tree))<br /> (enumerate-tree (rest tree)))))<br />(enumerate-tree (list 1 (list 2 (list 3 4)) 5))<br />(defn sum-odd-squares [tree]<br /> (accumulate<br /> + 0 (map square (filter odd? (enumerate-tree tree)))))<br />(defn even-fibs [n]<br /> (accumulate<br /> cons nil (filter even? (map fib (enumerate-interval 0 n)))))<br />(defn list-fib-squares [n]<br /> (accumulate<br /> cons nil (map square (map fib (enumerate-interval 0 n)))))<br />(list-fib-squares 10)<br />(defn product-of-squares-of-odd-elements [sequence]<br /> (accumulate * 1 (map square (filter odd? sequence))))<br />(product-of-squares-of-odd-elements (list 1 2 3 4 5))<br />(letfn [(salary [] <??>)<br /> (programmer? [] <??>)]<br /> (defn salary-of-highest-paid-programmer [records]<br /> (accumulate max 0 (map salary (filter programmer? records)))))<br /><br />;Exercise 2.23<br />(defn map-2.23 [p sequence]<br /> (accumulate (fn [x y] <??> nil sequence)))<br />(defn append-2.23 [seq1 seq2]<br /> (accumulate cons <??> <??>))<br />(defn length-2.23 [sequence]<br /> (accumulate <??> 0 sequence))<br /><br />;Exercise 2.34<br />(defn horner-eval [x coefficient-sequence]<br /> (accumulate (fn [this-coeff higher-term] <??>)<br /> 0<br /> coefficient-sequence))<br /><br />;Exercise 2.35<br />(defn count-leaves-2.35 [t]<br /> (accumulate <??> <??> (map <??> <??>)))<br /><br />;Exercise 2.36<br />(defn accumulate-n [op init seqs]<br /> (if (null? (first seqs))<br /> nil<br /> (cons (accumulate op init <??>)<br /> (accumulate-n op init <??>))))<br /><br />;Exercise 2.37<br />(defn dot-product [v w]<br /> (accumulate + 0 (map * v w)))<br />(defn matrix-*-vector [m v]<br /> (map <??> m))<br />(defn transpose [mat]<br /> (accumulate-n <??> <??> mat))<br />(defn matrix-*-matrix [m n]<br /> (let [cols (transpose n)]<br /> (map <??> m)))<br /><br />;Exercise 2.38<br />(def fold-right accumulate)<br />(defn fold-left [op initial sequence]<br /> (letfn [(iter [result rest-seq]<br /> (if (null? rest)<br /> result<br /> (iter (op result (first rest-seq))<br /> (rest rest-seq))))]<br /> (iter initial sequence)))<br />(fold-right / 1 (list 1 2 3))<br />(try<br /> (fold-left / 1 (list 1 2 3))<br /> (catch Exception e))<br />(fold-right list nil (list 1 2 3))<br />(try (fold-left list nil (list 1 2 3))<br /> (catch StackOverflowError e))<br /><br />;Exercise 2.39<br />(defn reverse-1 [sequence]<br /> (fold-right (fn [x y] <??>) nil sequence))<br />(defn reverse-2 [sequence]<br /> (fold-left (fn [x y] <??>) nil sequence))<br /><br />;Nested Mappings<br />(let [n 4]<br /> (accumulate<br /> append nil (map (fn [i]<br /> (map (fn [j] (list i j))<br /> (enumerate-interval 1 (- i 1))))<br /> (enumerate-interval 1 n))))<br />(defn flatmap [proc seq]<br /> (accumulate append nil (map proc seq)))<br />(defn prime-sum? [pair]<br /> (prime? (+ (first pair) (first (rest pair)))))<br />(defn make-pair-sum [pair]<br /> (list (first pair) (first (rest pair)) (+ (first pair) (first (rest pair)))))<br />(defn prime-sum-pairs [n]<br /> (map make-pair-sum<br /> (filter prime-sum? (flatmap<br /> (fn [i]<br /> (map (fn [j] (list i j))<br /> (enumerate-interval 1 (- i 1))))<br /> (enumerate-interval 1 n)))))<br />(defn permutations [s]<br /> (letfn [(remove [item sequence]<br /> (filter (fn [x] (not (= x item))) sequence))]<br /> (if (null? s)<br /> (list nil)<br /> (flatmap (fn [x]<br /> (map (fn [p] (cons x p))<br /> (permutations (remove x s))))<br /> s))))<br /><br />;Exercise 2.42<br />(letfn [(empty-board [] <??>)<br /> (safe? [] <??>)<br /> (adjoin-position [] <??>)]<br /> (defn queens [board-size]<br /> (letfn [(queen-cols [k]<br /> (if (= k 0)<br /> (list empty-board)<br /> (filter<br /> (fn [positions] (safe? k positions))<br /> (flatmap<br /> (fn [rest-of-queens]<br /> (map (fn [new-row]<br /> (adjoin-position<br /> new-row k rest-of-queens))<br /> (enumerate-interval 1 board-size)))<br /> (queen-cols (- k 1))))))]<br /> (queen-cols board-size))))<br /><br />;Exercise 2.43<br />(comment<br /> (flatmap<br /> (fn [new-row]<br /> (map (fn [rest-of-queens]<br /> (adjoin-position new-row k rest-of-queens))<br /> (queen-cols (- k 1))))<br /> (enumerate-interval 1 board-size)))<br /><br />;Chapter 2.2.4 A Picture Language<br />(declare wave beside flip-vert flip-horiz below up-split corner-split<br /> sub-vect make-vect add-vect origin-frame draw-line start-segment<br /> end-segment)<br />(defn flipped-pairs [painter]<br /> (let [painter2 (beside painter (flip-vert painter))]<br /> (below painter2 painter2)))<br />(comment<br /> (def wave2 (beside wave (flip-vert wave)))<br /> (def wave4 (below wave2 wave2))<br /> (def wave4 (flipped-pairs wave)))<br />(defn right-split [painter n]<br /> (if (= n 0)<br /> painter<br /> (let [smaller (right-split painter (- n 1))]<br /> (beside painter (below smaller smaller)))))<br />(defn up-split [painter n]<br /> (if (= n 0)<br /> painter<br /> (let [smaller (up-split painter (- n 1))]<br /> (below painter (beside smaller smaller)))))<br />(defn corner-split [painter n]<br /> (if (= n 0)<br /> painter<br /> (let [up (up-split painter (- n 1))<br /> right (right-split painter (- n 1))]<br /> (let [top-left (beside up up)<br /> bottom-right (below right right)<br /> corner (corner-split painter (- n 1))]<br /> (beside (below painter top-left)<br /> (below bottom-right corner))))))<br />(defn square-limit [painter n]<br /> (let [quarter (corner-split painter n)]<br /> (let [half (beside (flip-horiz quarter) quarter)]<br /> (below (flip-vert half half)))))<br />(defn square-of-four [tl tr bl br]<br /> (fn [painter]<br /> (let [top (beside (tl painter) (tr painter))<br /> bottom (beside (bl painter) (br painter))]<br /> (below bottom top))))<br />(defn flipped-pairs [painter]<br /> (let [combine4 (square-of-four identity flip-vert<br /> identity flip-vert)]<br /> (combine4 painter)))<br />(def rotate180 (comp flip-vert flip-horiz))<br />(defn square-limit [painter n]<br /> (let [combine4 (square-of-four flip-horiz identity<br /> rotate180 flip-vert)]))<br />(defn frame-coord-map [frame]<br /> (fn [v]<br /> (add-vect<br /> (origin-frame frame))))<br /><br />;Exercise 2.47<br />(defn make-frame [origin edge1 edge2]<br /> (list origin edge1 edge2))<br /><br />;Painters<br />(defn segments->painter [segment-list]<br /> (fn [frame]<br /> (for-each (fn [segment]<br /> (draw-line<br /> ((frame-coord-map frame)<br /> (start-segment segment))<br /> ((frame-coord-map frame)<br /> (end-segment segment))))<br /> segment-list)))<br />;Transforming and combining painters<br />(defn transform-painter [painter origin corner1 corner2]<br /> (fn [frame]<br /> (let [m (frame-coord-map frame)]<br /> (let [new-origin (m origin)]<br /> (painter (make-frame<br /> new-origin<br /> (sub-vect (m corner1) new-origin)<br /> (sub-vect (m corner2) new-origin)))))))<br />(defn flip-vert [painter]<br /> (transform-painter painter<br /> (make-vect 0.0 1.0)<br /> (make-vect 1.0 1.0)<br /> (make-vect 0.0 0.0)))<br />(defn shrink-to-upper-right [painter]<br /> (transform-painter<br /> painter (make-vect 0.5 0.5)<br /> (make-vect 1.0 0.5) (make-vect 0.5 1.0)))<br />(defn rotate80 [painter]<br /> (transform-painter painter<br /> (make-vect 1.0 0.0)<br /> (make-vect 1.0 1.0)<br /> (make-vect 0.0 0.0)))<br />(defn squash-inwards [painter]<br /> (transform-painter painter<br /> (make-vect 0.0 0.0)<br /> (make-vect 0.65 0.35)<br /> (make-vect 0.35 0.65)))<br />(defn beside [painter1 painter2]<br /> (let [split-point (make-vect 0.5 0.0)]<br /> (let [paint-left<br /> (transform-painter<br /> painter1<br /> (make-vect 0.0 0.0)<br /> split-point<br /> (make-vect 0.0 1.0))<br /> paint-right<br /> (transform-painter<br /> painter2<br /> split-point<br /> (make-vect 1.0 0.0)<br /> (make-vect 0.5 1.0))]<br /> (fn [frame]<br /> (paint-left frame)<br /> (paint-right frame)))))</pre></div></div>Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com2tag:blogger.com,1999:blog-4197673488000870373.post-9172389307134709242017-01-08T17:00:00.003+01:002017-01-08T17:00:52.833+01:00What Clojure is missing...Ok, now I have played with Clojure for a lot of time.<br />I know how to write clojure programs, how to write in a functional style (on a base-medium level).<br />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 ....<br />Lately I built a web app to handle the deployment through Docker of our Web Application and I was thinking about using Clojure.<br />This is how the discussion went (more or less):<br /><b>Marco</b>: "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"<br /><b>Other People</b> (in this company before starting we discuss pro and contro of every decision):<br />"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"<br /><b>Marco: "</b>Well I was thinking of using Luminus, it's quite well documented and it has already been used in production from what I know"<br /><b>Others: </b>"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"<br /><b>Marco: </b>"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"<br />etc...<br /><br />Unfortunately after this sentence I was not able to convince anymore my co-workers... and that's the reason for my post.<br />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 <b>Convention Over Configuration </b>really help in this situation.<br />Clojure is missing a good framework with <b>Convention Over Configuration</b>, 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.<br />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.<br />It's true, I'm a Clojure and functional programmer <b>Noob</b>. But also when I will be a <b>Pro </b>Clojure programmer, my main concern will be, Clojure <b>Noobs</b> will soon join me, I want to easy their life, I want them to be productive.<br />I will continue my travel to become a <b>Pro </b>Clojure programmer, with this in mind, I have to create something that will give me the ability to reply to my co-workers:<br />"Yes this is the standard way to do things and can be easily learn from new people, this is the "<b>Spring</b>"<b> </b>framework of Clojure"<br />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.<br /><br />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 <a href="http://arachne-framework.org/">Arachne Framework</a> will fix this issue but until documentation will be available I will not have a clue...Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-17511786151726508182017-01-06T11:48:00.000+01:002017-01-16T12:24:26.158+01:00SICP in Clojure: Chapter 1With a new year some new objectives should be set.<br /><br /><ol><li>Learn French</li><li>Understand better functional programming</li><li>Use Clojure in a real project (if you need help in some real project let me know :) )</li></ol><div>This post is about the 2nd point. To learn more about functional programming I'm reading <i style="background-color: white;"><a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs" style="background-color: white; font-weight: bold;">Structure and Interpretation of Computer Programs</a>.</i><span style="background-color: white;"> This is really a great book but all the examples are in Lisp.</span></div><div><span style="background-color: white;">To make it more actual I'm rewriting all the examples in clojure (and some exercises too). <b style="font-style: italic;"> </b></span></div><div><span style="background-color: white;">I think it can be useful to others too, so here it is chapter 1:</span><br /><span style="background-color: white;"><br /></span><br /><pre class="brush: csharp">(ns sicp.chapter-1)<br /><br />;1.1 Expressions<br />(+ 137 349)<br />(- 1000 334)<br />(* 5 99)<br />(/ 10 5)<br />(+ 2.7 10)<br />(+ 21 35 12 7)<br />(* 25 4 12)<br />(+ (* 3 5) (- 10 6))<br />(+ (* 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6))<br />(+ (* 3<br /> (+ (* 2 4)<br /> (+ 3 5)))<br /> (+ (- 10 7)<br /> 6))<br /><br />;1.2 Naming and the Environment<br />(def size 2)<br />size<br />(* 5 size)<br />(def pi 3.14159)<br />(def radius 10)<br />(* pi (* radius radius))<br />(def circumference (* 2 pi radius))<br />circumference<br /><br />;1.1.3 Evaluating Combinations<br />(* (+ 2 (* 4 6))<br /> (+ 3 5 7))<br /><br />;1.1.4 Compound Procedures<br />(defn square [x] (* x x))<br /><br />;(defn <name> [<formal parameters>] <body>)<br />(square 21)<br />(square (+ 2 5))<br />(square (square 3))<br />(defn sum-of-squares<br /> [x y]<br /> (+ (square x) (square y)))<br />(sum-of-squares 3 4)<br />(defn f [a]<br /> (sum-of-squares (+ a 1) (* a 2)))<br />(f 5)<br /><br />;1.1.5 The Substitution Model for Procedure Applincation<br />(f 5)<br />(sum-of-squares (+ 5 1) (* 5 2))<br />(+ (square 6) (square 10))<br />(+ 36 100)<br />(sum-of-squares (+ 5 1) (* 5 2))<br />(+ (square (+ 5 1)) (square (* 5 2)))<br />(+ (* (+ 5 1) (+ 5 1)) (* (* 5 2) (* 5 2)))<br />(+ (* 6 6) (* 10 10))<br />(+ 36 100)<br />(defn abs [x]<br /> (cond (> x 0) x<br /> (= x 0) 0<br /> (< x 0 ) (- x)))<br />(comment<br /> (cond <p1> <e1><br /> <p2> <e2><br /> ...<br /> <pn> <en><br /> :else <e>))<br />(defn abs [x]<br /> (cond (< x 0) (- x)<br /> :else x))<br />(defn abs [x]<br /> (if (< x 0)<br /> (- x)<br /> x))<br />(comment<br /> (if <predicate><br /> <consequent><br /> <alternative>))<br />(comment<br /> (and <e1> .... <en>))<br />(comment<br /> (or <e1> ... <en>))<br />(comment<br /> (not <e>))<br />(comment (and (> x 5) (< x 10)))<br />(defn >= [x y]<br /> (or (> x y) (= x y)))<br />(defn >= [x y]<br /> (not (< x y)))<br />;Exercise 1.1<br />10<br />(+ 5 3 4)<br />(- 9 1)<br />(/ 6 2)<br />(+ (* 2 4) (- 4 6))<br />(def ^:private a 3)<br />(def ^:private b (+ a 1))<br />(+ a b (* a b))<br />(= a b)<br />(if (and (> b a) (< b (* a b)))<br /> b<br /> a)<br />(cond (= a 4) 6<br /> (= b 4) (+ 6 7 a)<br /> :else 25)<br />(+ 2 (if (> b a) b a))<br />(* (cond (> a b) a<br /> (< a b) b<br /> :else -1)<br /> (+ a 1))<br /><br />;Exercise 1.2<br />(/ (+ 5<br /> 4<br /> (- 2<br /> (- 3<br /> (+ 6<br /> (/ 4 5)))))<br /> (* 3<br /> (- 6 2)<br /> (- 2 7)))<br /><br />;Exercise 1.3<br />(defn ex1-3<br /> [a b c]<br /> (cond<br /> (and (< a b) (< a c)) (+ (square b) (square c))<br /> (and (< b a) (< b c)) (+ (square a) (square c))<br /> :else (+ (square a) (square b))))<br /><br />;Exercise 1.4<br />(defn a-plus-abs-b<br /> [a b]<br /> ((if (> b 0) + -) a b))<br /><br />;Example 1.1.7<br />(defn good-enough? [guess x]<br /> (< (abs (- (square guess) x)) 0.001))<br />(defn average [x y]<br /> (/ (+ x y) 2))<br />(defn improve [guess x]<br /> (average guess (/ x guess)))<br />(defn sqrt-iter [guess x]<br /> (if (good-enough? guess x)<br /> guess<br /> (sqrt-iter (improve guess x) x)))<br />(defn sqrt [x]<br /> (sqrt-iter 1.0 x))<br />(sqrt 9)<br />(sqrt (+ (sqrt 2) (sqrt 3)))<br />(square (sqrt 1000))<br /><br />;Exercise 1.6<br />(defn new-if [predicate then-clause else-clause]<br /> (cond<br /> predicate then-clause<br /> :else else-clause))<br />(new-if (= 2 3) 0 5)<br />(new-if (= 1 1) 0 5)<br />(defn new-sqrt-iter [guess x]<br /> (new-if (good-enough? guess x)<br /> guess<br /> (new-sqrt-iter (improve guess x) x)))<br />(defn new-sqrt [x]<br /> (new-sqrt-iter 1.0 x))<br /><br />; (new-sqrt 9) -> Overflow<br /><br />;Exercise 1.7<br />(good-enough?<br /> 1000000000000000000000<br /> 1000000000000000000000)<br />(good-enough? 1 1)<br />(defn new-good-enough? [prev-guess new-guess]<br /> (< (abs (- new-guess prev-guess)) 0.001))<br />(new-good-enough?<br /> 1000000000000000000000<br /> 1000000000000000000000)<br />(defn new-sqrt-iter-2 [guess x]<br /> (if (new-good-enough? guess (improve guess x))<br /> (improve guess x)<br /> (new-sqrt-iter-2 (improve guess x) x)))<br />(defn new-sqrt-2 [x]<br /> (new-sqrt-iter-2 1.0 x))<br />(new-sqrt-2 9)<br /><br />;Exercise 1.8<br />(defn improve-cube-root [guess x]<br /> (/<br /> (+ (/ x (square guess))<br /> (* 2 guess))<br /> 3))<br />(defn cube-root-iter [guess x]<br /> (if (new-good-enough? guess (improve-cube-root guess x))<br /> (improve-cube-root guess x)<br /> (cube-root-iter (improve-cube-root guess x) x)))<br />(defn cube-root [x]<br /> (cube-root-iter 3.0 x))<br />(cube-root 27)<br /><br />;Chapter 1.1.8<br />(defn square [x] (* x x))<br />(defn double [x] (+ x x))<br />(defn square [x] (Math/exp (double (Math/log x))))<br />(square 3)<br />(defn sqrt [x]<br /> (letfn [(good-enough? [guess x]<br /> (< (abs (- (square guess) x)) 0.001))<br /> (improve [guess x] (average guess (/ x guess)))<br /> (sqrt-iter [guess x]<br /> (if (good-enough? guess x)<br /> guess<br /> (sqrt-iter (improve guess x) x)))]<br /> (sqrt-iter 1.0 x)))<br />(sqrt 9)<br />(defn sqrt [x]<br /> (letfn [(good-enough? [guess]<br /> (< (abs (- (square guess) x)) 0.001))<br /> (improve [guess] (average guess (/ x guess)))<br /> (sqrt-iter [guess]<br /> (if (good-enough? guess)<br /> guess<br /> (sqrt-iter (improve guess))))]<br /> (sqrt-iter 1.0)))<br />(sqrt 9)<br /><br />;Chapter 1.2<br />(defn factorial [n]<br /> (if (= n 1)<br /> 1<br /> (* n (factorial (- n 1)))))<br />(factorial 6)<br />(defn factorial [n]<br /> (letfn [(fact-iter [product counter max-count]<br /> (if (> counter max-count)<br /> product<br /> (fact-iter (* counter product)<br /> (+ counter 1)<br /> max-count)))]<br /> (fact-iter 1 1 n)))<br />(factorial 6)<br /><br />;Execise 1.9<br />(letfn [(inc [x] (+ 1 x))<br /> (dec [x] (- x 1))]<br /> (defn + [a b]<br /> (if (= a 0) b (inc (+ (dec a) b))))<br /> (defn + [a b]<br /> (if (= a 0) b (+ (dec a) (inc b)))))<br />(def + clojure.core/+)<br /><br />;Exercise 1.10<br />(defn A [x y]<br /> (cond<br /> (= y 0) 0<br /> (= x 0) (* 2 y)<br /> (= y 1) 2<br /> :else (A (- x 1) (A x (- y 1)))))<br />(A 1 10)<br />(A 2 4)<br />(A 3 3)<br />(letfn [(f [n] (A 0 n))<br /> (g [n] (A 1 n))<br /> (h [n] (A 2 n))<br /> (k [n] (* 5 n n))])<br /><br />;Chapter 1.2.2<br />(defn fib [n]<br /> (cond<br /> (= n 0) 0<br /> (= n 1) 1<br /> :else (+ (fib (- n 1))<br /> (fib (- n 2)))))<br />(defn fib [n]<br /> (letfn [(fib-iter [a b count]<br /> (if (= count 0)<br /> b<br /> (fib-iter (+ a b) a (- count 1))))]<br /> (fib-iter 1 0 n)))<br />(fib 10)<br /><br />;Example Counting Change<br />(defn first-denomination [kind-of-coins]<br /> (cond<br /> (= kind-of-coins 1) 1<br /> (= kind-of-coins 2) 5<br /> (= kind-of-coins 3) 10<br /> (= kind-of-coins 4) 25<br /> (= kind-of-coins 5) 50 ))<br />(defn cc [amount kind-of-coins]<br /> (cond<br /> (= amount 0) 1<br /> (or (< amount 0) (= kind-of-coins 0)) 0<br /> :else (+<br /> (cc amount (- kind-of-coins 1))<br /> (cc (- amount<br /> (first-denomination kind-of-coins))<br /> kind-of-coins))))<br />(defn count-change [amount]<br /> (cc amount 5))<br />(count-change 100)<br />(count-change 200)<br /><br />;Exercise 1.11<br />(defn f1-11 [n] ;Recursive<br /> (if (< n 3)<br /> n<br /> (+ (f (- n 1))<br /> (* 2 (f (- n 2)))<br /> (* 3 (f (- n 3))))))<br /><br />;Chapter 1.2.4<br />(defn expt [b n]<br /> (if (= n 0)<br /> 1<br /> (* b (expt b (- n 1)))))<br />(expt 4 3)<br />(defn expt [b n]<br /> (letfn [(expt-iter [b counter product]<br /> (if (= counter 0)<br /> product<br /> (expt-iter b (- counter 1) (* b product))))]<br /> (expt-iter b n 1)))<br />(expt 4 3)<br />(defn fast-expt [b n]<br /> (cond<br /> (= n 0) 1<br /> (even? n) (square (fast-expt b (/ n 2)))<br /> :else (* b (fast-expt b (- n 1)))))<br />(fast-expt 4 3)<br /><br />;Exercise 1.19<br />(comment<br /> (defn fib [n]<br /> (letfn [(fib-iter [a b p q count]<br /> (cond<br /> (= count 0) b<br /> (even? count) (fib-iter a<br /> b<br /> <??><br /> <??><br /> (/ count 2))<br /> :else (fib-iter (+ (* b q) (* a q) (* a p))<br /> (+ (* b p) (* a q))<br /> p<br /> q<br /> (- count 1))))])))<br /><br />;Chapter 1.2.5 Greatest Common Divisors<br />(defn gcd [a b]<br /> (if (= b 0)<br /> a<br /> (gcd b (rem a b))))<br /><br />;Chapter 1.2.6 Example: Testing for Primality<br />(defn smallest-divisor [n]<br /> (letfn [(divides? [a b]<br /> (= (rem b a) 0))<br /> (find-divisor [n test-divisor]<br /> (cond<br /> (> (square test-divisor) n) n<br /> (divides? test-divisor n) test-divisor<br /> :else (find-divisor n (+ test-divisor 1))))]<br /> (find-divisor n 2)))<br />(defn prime? [n]<br /> (= n (smallest-divisor n)))<br /><br />;Fermat Test<br />(defn expmod [base exp m]<br /> (cond<br /> (= exp 0) 1<br /> (even? exp) (rem<br /> (square (expmod base (/ exp 2) m))<br /> m)<br /> :else (rem<br /> (* base (expmod base (- exp 1) m))<br /> m)))<br />(defn fermat-test [n]<br /> (letfn [(try-it [a]<br /> (= (expmod a n n) a))]<br /> (try-it (+ 1 (rand (- n 1))))))<br />(defn fast-prime? [n times]<br /> (cond<br /> (= times 0) true<br /> (fermat-test n) (fast-prime? n (- times 1))<br /> :else false))<br /><br />;Exercise 1.21<br />(smallest-divisor 199)<br />(smallest-divisor 1999)<br />(smallest-divisor 19999)<br /><br />;Exercise 1.22<br />(defn runtime [] (System/currentTimeMillis))<br />(defn timed-prime-test [n]<br /> (letfn [(report-prime [elapsed-time]<br /> (letfn []<br /> (println " *** ")<br /> (println elapsed-time)))<br /> (start-prime-test [n start-time]<br /> (if (prime? n)<br /> (report-prime (- (runtime) start-time))))]<br /> (println "")<br /> (println n)<br /> (start-prime-test n (runtime))))<br /><br />;Exercise 1.25<br />(defn expmod [base exp m]<br /> (rem (fast-expt base exp) m))<br /><br />;Exercise 1.26<br />(defn expmod [base exp m]<br /> (cond<br /> (= exp 0) 1<br /> (even? exp) (rem (* (expmod base (/ exp 2) m)<br /> (expmod base (/ exp 2) m))<br /> m)<br /> :else<br /> (rem (* base<br /> (expmod base (- exp 1) m))<br /> m)))<br /><br />;Chapter 1.3<br />(defn cube [x] (* x x x))<br /><br />;Chapter 1.3.1<br />(defn sum-integers [a b]<br /> (if (> a b)<br /> 0<br /> (+ a (sum-integers (+ a 1) b))))<br />(defn sum-cubes [a b]<br /> (if (> a b)<br /> 0<br /> (+ (cube a)<br /> (sum-cubes (+ a 1) b))))<br />(defn pi-sum [a b]<br /> (if (> a b)<br /> 0<br /> (+ (/ 1.0 (* a (+ a 2)))<br /> (pi-sum (+ a 4) b))))<br />(defn sum [term a next b]<br /> (if (> a b)<br /> 0<br /> (+ (term a)<br /> (sum term (next a) next b))))<br />(defn inc [n] (+ n 1))<br />(defn sum-cubes [a b]<br /> (sum cube a inc b))<br />(sum-cubes 1 100)<br />(defn sum-integers [a b]<br /> (letfn [(identity [x] x)]<br /> (sum identity a inc b)))<br />(sum-integers 1 5)<br />(defn pi-sum [a b]<br /> (letfn [(pi-term [x] (/ 1.0 (* x (+ x 2))))<br /> (pi-next [x] (+ x 4))]<br /> (sum pi-term a pi-next b)))<br />(* 8 (pi-sum 1 1000))<br />(defn integral [f a b dx]<br /> (letfn [(add-dx [x] (+ x dx))]<br /> (* (sum f (+ a (/ dx 2.0)) add-dx b)<br /> dx)))<br />(integral cube 0 1 0.01)<br />(integral cube 0 1 0.001)<br /><br />;Chapter 1.3.2 Constructing Procedures Using lambda<br />(fn [x] (+ x 4))<br />#(+ % 4)<br />(fn [x] (/ 1.0 (* x (+ x 2))))<br />#(/ 1.0 (* % (+ % 2)))<br />(defn pi-sum [a b]<br /> (sum #(/ 1.0 (* % (+ % 2)))<br /> a<br /> #(+ % 4)<br /> b))<br />(defn integral [f a b dx]<br /> (* (sum f<br /> (+ a (/ dx 2.0))<br /> #(+ % dx)<br /> b)<br /> dx))<br />(comment (<fn> [<formal-parameters] <body>) or #(<body> with % as x))<br />(defn plus4 [x] (+ x 4))<br />(def plus4 #(+ % 4))<br />(#(+ %1 %2 (square %3)) 1 2 3)<br /><br />;Using let to create local variables<br />(defn f [x y]<br /> (letfn [(f-helper [a b]<br /> (+ (* x (square a))<br /> (* y b)<br /> (* a b)))]<br /> (f-helper (+ 1 (* x y))<br /> (- 1 y))))<br />(f 1 2)<br />(defn f [x y]<br /> ((fn [a b]<br /> (+ (* x (square a))<br /> (* y b)<br /> (* a b)))<br /> (+ 1 (* x y))<br /> (- 1 y)))<br />(f 1 2)<br />(defn f [x y]<br /> (let [a (+ 1 (* x y))<br /> b (- 1 y)]<br /> (+ (* x (square a))<br /> (* y b)<br /> (* a b))))<br />(f 1 2)<br />(let [x 5]<br /> (+ (let [x 3]<br /> (+ x (* x 10)))<br /> x))<br />(let [x 2]<br /> (let [x 3<br /> y (+ x 2)]<br /> (* x y)))<br />(defn f [x y]<br /> (let [a (+ 1 (* x y))<br /> b (- 1 y)]<br /> (+ (* x (square a))<br /> (* y b)<br /> (* a b))))<br /><br />;Chapter 1.3.3 Procedures as General Methods<br />(defn close-enough? [x y]<br /> (< (abs (- x y)) 0.001))<br />(defn search [f neg-point pos-point]<br /> (let [midpoint (average neg-point pos-point)]<br /> (if (close-enough? neg-point pos-point)<br /> midpoint<br /> (let [test-value (f midpoint)]<br /> (cond<br /> (pos? test-value) (search f neg-point midpoint)<br /> (neg? test-value) (search f midpoint pos-point)<br /> :else midpoint)))))<br />(defn error [s v1 v2]<br /> (println (str s " " v1 " " v2 )))<br />(defn half-interval-method [f a b]<br /> (let [a-value (f a)<br /> b-value (f b)]<br /> (cond<br /> (and (neg? a-value) (pos? b-value)) (search f a b)<br /> (and (neg? b-value) (pos? a-value)) (search f b a)<br /> :else (error "Values are not of opposite sign" a b))))<br />(def sin #(Math/sin %))<br />(def cos #(Math/cos %))<br />(half-interval-method sin 2.0 4.0)<br />(half-interval-method #(- (* % % %) (* 2 %) 3) 1.0 3.0)<br /><br />;Finding fixed points of functions<br />(def tolerance 0.00001)<br />(defn fixed-point [f first-guess]<br /> (letfn [(close-enough? [v1 v2]<br /> (< (abs (- v1 v2)) tolerance))<br /> (try-f [guess]<br /> (let [next (f guess)]<br /> (if (close-enough? guess next)<br /> next<br /> (try-f next))))]<br /> (try-f first-guess)))<br />(fixed-point #(+ (sin %) (cos %)) 1.0)<br />(defn sqrt [x]<br /> (fixed-point #(/ x %)<br /> 1.0))<br />(defn sqrt [x]<br /> (fixed-point #(average % (/ x %))<br /> 1.0))<br /><br />;Chapter 1.3.4 Procedures as Returned Values<br />(defn average-damp [f]<br /> #(average % (f %)))<br />((average-damp square) 10)<br />(defn sqrt [x]<br /> (fixed-point (average-damp #(/ x %))<br /> 1.0))<br />(defn cube-root [x]<br /> (fixed-point (average-damp #(/ x %))<br /> 1.0))<br />(def dx tolerance)<br />(defn- deriv [g]<br /> #(/ (- (g (+ % dx))<br /> (g %))<br /> dx))<br />(defn cube [x] (* x x x))<br />((deriv cube) 5)<br />(defn newton-transform [g]<br /> #(- % (/ (g %) ((deriv g) %))))<br />(defn newtons-method [g guess]<br /> (fixed-point (newton-transform g) guess))<br />(defn sqrt [x]<br /> (newtons-method<br /> #(- (square %) x) 1.0))<br />(defn fixed-point-of-transform [g tranform guess]<br /> (fixed-point (tranform g) guess))<br />(defn sqrt [x]<br /> (fixed-point-of-transform #(/ x %) average-damp 1.0))<br />(defn sqrt [x]<br /> (fixed-point-of-transform<br /> #(- (square %) x) newton-transform 1.0))<br /><br /><br /></pre></div>Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com2tag:blogger.com,1999:blog-4197673488000870373.post-13655869203225013332015-01-21T11:57:00.000+01:002015-01-21T11:57:08.486+01:00Light TableOk after some work with it I have to say that it's really one of the easiest IDE to start with Clojure.<br />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.<br />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.1Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-9205394583922801092015-01-19T20:57:00.000+01:002015-01-19T21:16:12.504+01:00Clojure Ide: LightTableOk it has been some time since I start using clojure.<br />I have to restart... and what is better than starting with the IDE.<br />I want to give <a href="http://lighttable.com/">LightTable</a> a try again, it was interesting last time I tried it.<br />It's open source (under MIT) and I like the design.<br />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....<br />Ok let's read docs..<br />"With Clojure...<br /><ol style="-webkit-text-stroke-width: 0px; background-color: #202020; background-position: initial initial; background-repeat: initial initial; border: 0px; color: #dddddd; counter-reset: numbers 0; font-family: 'Open sans', sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 21px; list-style: none; margin: 0px 0px 0px 15px; orphans: auto; padding: 5px; text-align: start; text-indent: 0px; text-transform: none; vertical-align: baseline; white-space: normal; widows: auto; word-spacing: 0px;"><li style="border-left-color: rgb(119, 170, 255); border-left-style: solid; border-width: 0px 0px 0px 1px; counter-increment: numbers 1; font-family: inherit; font-size: 14px; font-style: inherit; font-weight: inherit; margin: 0px 0px 5px 20px; padding: 0px 0px 0px 8px; position: relative; vertical-align: baseline;">In the view menu click the<span class="Apple-converted-space"> </span><code style="background-color: #3d3e3c; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; border: 0px; font-family: Courier, monospace; font-size: 10pt; font-style: inherit; font-weight: inherit; margin: 0px; padding: 2px; vertical-align: baseline;">commands</code><span class="Apple-converted-space"> </span>item (or press Ctrl+Space)</li></ol>Where is the <i>commands </i>item....., ok I go with the Ctrl+Space, but I don't like when they point me to something that don't exist...<br />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.<br />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<br />But ok I have created the first 'workspace' now I will have to refresh my clojure memory. See you soon.<br /><br />After a while:<br />Delete file --- double confirm by default.... not user friendly<br /><br />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<br /><br /><br />After another half an hour:<br />Sorry, LightTable is out, I want to change the clojure version, I can't find a way.<br />Sorry for that, I like the design but is not user friendly.<br /><br />15 minutes after:<br />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) Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com4tag:blogger.com,1999:blog-4197673488000870373.post-43970080163109892212015-01-19T20:18:00.001+01:002015-01-19T21:19:38.778+01:00Clojure + Clojure Script CMSOk 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:<br /><ul><li>Compojure (first I thought ring)</li><li>Bootstrap</li></ul>For now I will go with this. I will try the best approach I can think:<br /><br /><b>Do easy thing first, cover everything with tests, use more tools only when needed</b><br /><br />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.<br />Have a nice evening, post to you soon.Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com2tag:blogger.com,1999:blog-4197673488000870373.post-70842511258570241642015-01-16T16:26:00.001+01:002015-01-16T16:26:57.579+01:00Clojure 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.<br>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.<br>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).<br>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).<br>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.Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com5tag:blogger.com,1999:blog-4197673488000870373.post-40118567018276929612015-01-15T10:51:00.001+01:002015-01-15T10:51:25.919+01:00Clojure, Scala, Java 8Here I am, back finally after an interesting year. I changed my job, now I'm working for <a href="http://www.jbilling.com/">jBilling</a> from home. Working in a remote company is a challenging experience, and in particular it let you understand that clean code (well written, full tested and easy to extend and change) is something that you can't live without. This year I want to start a project to search for the perfect software combination to create a complex project. Until now I have never started working on a personal project, now I think I'm ready. I will create a CMS. The idea is to try to reproduce the same things with 3 different languages, Java 8, Clojure and Scala in the backend. For the frontend I will go with Angular JS, that will communicate through Rest services to the backend. If you have any suggestion on the framework that I will have to use feel free to comment here. I would like to do something that will be interesting for anyone that is going to read this. Talk to you soon. Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com4tag:blogger.com,1999:blog-4197673488000870373.post-22349558843020600312013-11-17T18:34:00.000+01:002013-11-17T18:34:42.347+01:00Functional programming and Assignment 2I've solved the assignment 2 in Scala, now I would like to prepare the same in Clojure but I'm a little disappoined. Reading inside the assignment 2 classes I can't find any without a mutable state.... where is the functional programming? I'll write the assignment 2 in a functional style way. But it will took me some time. Meanwhile I'm disappointed, the first Scala course was all based on functional programming and now after only one week it is disappeared. Can we use functional programming style, or on the first simple project we do we will use only imperative style and forgot about the functional part?Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com3tag:blogger.com,1999:blog-4197673488000870373.post-15563184090875286862013-11-12T23:59:00.000+01:002013-11-13T00:05:10.784+01:00Week 2: Circuit Simulation, Functional WiresMmm actually I think that write Protocol and Record is not so so "Clojure's Style".<br />What do you think about this implementation? <div><script src="https://gist.github.com/marcomanzi/a3861a1df58ff4f65397.js"></script></div>I'm learning Clojure.. I'm not a Guru so I'm trying to always improve my "Clojure Functional Style".<br />I'll really appreciate any opinion you have on this!! :DMarco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-72346624969346452522013-11-11T22:49:00.002+01:002013-11-11T22:58:46.420+01:00Week2: Circuit Simulation, WiresThis week's first 3 videos are a introduction to state management inside a functional language, actually I can't read slides from video one, so I'll give you a Bank Account conversion in Clojure as soon as the slide will be out. In the second and the third video there isn't any code that can be usefull written in clojure (actually I can't understand what I had to learn from the third video... ). In the other videos video Martin start the implementation of a domain specifil language to simulate circuits.<br />This are the Wires, rewritten in Clojure:<br /><div><script src="https://gist.github.com/marcomanzi/ae0f4b863bed54527c58.js"></script></div>Actually I'm thinking a lot on differences beetween this two languages.<br />I think that to create DSL Scala has the huge advantage of type system, but I think that if we can build these kind of DSL we will be in jail...<br />One great programmer in each society that will build the DSL, and all low-profile programmer that will use it without knowing anything of real Scala.<br />Another little consideration. What the heck is this O_o:<br /><div><script src="https://gist.github.com/marcomanzi/9f362326bcf6732b9b55.js"></script></div>Ok the Scala's <i>match </i>is AWESOME, I said it in another post. But this is quite confusing, I had to watch the video 3 times to understand what was appening, in Clojure that are a lot of parenthesis, and someone can be frustrated from it, but here we need some parenthesis. The part with <= => it's very horrible in my opinion.<br />For now It's all :D, I'll come soon with the rest of Circuit implementation.<br /><br />PS: The assignment will be quite a challenge .. there is also a Display for the Epidemic Simulation... I need days of 30 hours ....Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-67805917501570469362013-11-11T13:45:00.000+01:002013-11-11T13:45:00.863+01:00Week 2 is OUTO_o week 2 is out and the Assignment seems AWESOME :D<br />Clojure code will be on the blog as soon as possible... I think I can't sleep anymore....Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-89887013841878961002013-11-10T19:38:00.001+01:002013-11-10T19:38:31.350+01:00Assignment 1 done in Clojure and ScalaI have solved the Assignment in this 2 languages...<br />My opinion....<br /><b>Clojure: </b>I know more this languages, I had fun solve the assignment with clojure check, but actually I can say it's a good start but it has to be improved.<br />The problem was OO designed, so the solution and the assignment design it's not as great as I would like.<br />If I'll have time I'll come back to this assignment to re-design it to be more "clojure-friendly"<br /><b>Scala: </b>I did it in Scala, it was quite a shock to write because it was really easy to solve writing generators and properties. I think ScalaCheck is a great library, and the syntax of the solution is more clear than Clojure's one. The <i style="font-weight: bold;">match </i>of Scala is absolutely AWESOME.<br />I'll post my solution after the hard deadline :)Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-55227949220753091202013-11-09T22:03:00.000+01:002013-11-10T02:34:29.345+01:00Assignment 1And the assignment 1 in clojure is here finally :), it has been quite hard to convert it.<br /><div>I have rewritten the heap without doing any change in the design to make the same questions that are in the scala's assigment.</div><div>Actually the properties have to be done as functions. </div><div>The properties function are in the file quick_check_properties.clj</div><div><script src="https://gist.github.com/marcomanzi/c1996ba60478cf1191ed.js"></script></div><div><br />As said the assignment instructions you have to write a good number of properties check to make all test pass.<br />If you launch "lein test" in the directory of git you will see there are 5 test that fail.<br />They will pass when you will write the properties that check the fault in the 5 bogus implementation.<br />I'll post the solution after the hard date, in this way I'll not not give any hint.<br />The Heap implementations are made with protocols, actually I think it his quite a bad implementation, probably made for educational purpouse, if I have time I'll make a better implementation with multi methods.<br />Let me know what do you think, I'm new also to clojure, so I'll appreciate any tip/hint you can gave me :)<br />For any question feel free to comment I'll reply as soon as possible.<br />Again, the repository is here <a href="https://github.com/marcomanzi/reactiveclojure">https://github.com/marcomanzi/reactiveclojure</a>, you will find the quick_check_properties.clj where you have to write the functions to solve the assignment.<br /><br /><br />NB: I'm working on it, there are some problems but I'll fix it soon!! :)....<br />02:33--> Assignment is ready, you can solve it :), have fun</div>Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com2tag:blogger.com,1999:blog-4197673488000870373.post-75904204444066788982013-11-08T17:22:00.001+01:002013-11-08T17:23:24.894+01:00GitHub repositoryLike i wrote in About this Blog, there is a repository (that I'll update while the course go on) with the code:<br /><br /><a href="https://github.com/marcomanzi/reactiveclojure">https://github.com/marcomanzi/reactiveclojure</a><br /><br />Stay in touch :)Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0tag:blogger.com,1999:blog-4197673488000870373.post-27246007961686800542013-11-07T22:36:00.000+01:002013-11-07T22:42:36.195+01:00Week1 VideosIn the first week Martine spoke about the importance of Reactive Programming, I suggest you to watch the videos of the course (<a href="https://www.coursera.org/course/reactive">Principles of Reactive Programming</a>).<br /><br /><h3>Code for video: Recap: Functions and Pattern Matching</h3>In this video there is an implementation of a Json parser with case classes, and a show methods, one possible implementation in clojure is:<br /><div><script src="https://gist.github.com/marcomanzi/360f9f9b8642d721d7e2.js"></script></div><br />Here I used a simple Map with Json inside, the show method is <i>pretty_json</i>, instead of match I used multi function.<br /><br /><h3>Code for video: Functional Random Generators</h3><div>In this video Martin introduce the idea of functional generators to use for tests made with ScalaCheck, we will use <a href="https://github.com/jbondeson/clojurecheck">clojurecheck </a>that is a property base testing framework like ScalaCheck.</div><div>The code of generators is:</div><div><script src="https://gist.github.com/marcomanzi/e570d6d60c9469ad2be2.js"></script></div>I jumped the two recap video on language because I think that who came on this blog is a clojure developer, but if you want I can make a little tutorial on clojure.Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com1Italia41.87194 12.56737999999995741.87194 12.567379999999957 41.87194 12.567379999999957tag:blogger.com,1999:blog-4197673488000870373.post-80417238386726440832013-11-07T17:59:00.001+01:002013-11-07T17:59:30.063+01:00WelcomeThis blog will be used to make lessons on Reactive Programming using clojure.<br />It will follow the <a href="https://www.coursera.org/course/reactive" target="_blank">Principles of Reactive Programming</a> by Erik Meijer, Martin Odersky and Roland Kuhn but it will use Clojure to make the same things.Marco Manzihttps://plus.google.com/104498743450890257118noreply@blogger.com0