{"id":314,"date":"2012-08-10T22:25:31","date_gmt":"2012-08-10T12:25:31","guid":{"rendered":"http:\/\/juliangamble.com\/blog\/?p=314"},"modified":"2013-12-27T10:32:52","modified_gmt":"2013-12-26T23:32:52","slug":"the-little-schemer-in-clojure-chapter-4-numbers-games","status":"publish","type":"post","link":"https:\/\/juliangamble.com\/blog\/2012\/08\/10\/the-little-schemer-in-clojure-chapter-4-numbers-games\/","title":{"rendered":"The Little Schemer in Clojure \u2013 Chapter 4 \u2013 Numbers Games"},"content":{"rendered":"<p><em>This is the fourth Chapter of a series of posts about porting\u00a0<a href=\"http:\/\/www.ccs.neu.edu\/home\/matthias\/BTLS\/\">The Little Schemer<\/a>\u00a0to Clojure. You may wish to\u00a0<a href=\"http:\/\/juliangamble.com\/blog\/2012\/07\/20\/the-little-schemer-in-clojure\/\">read the intro<\/a>.<\/em><\/p>\n<p>You&#8217;ll notice that in the first three chapters, we <a href=\"http:\/\/juliangamble.com\/blog\/2012\/07\/20\/the-little-schemer-in-clojure-chapter-1\/\">introduced lists [Ch1]<\/a>, then we <a href=\"http:\/\/juliangamble.com\/blog\/2012\/07\/29\/the-little-schemer-in-clojure-chapter-2\/\">pulled things out of lists [Ch2]<\/a>, and then we <a href=\"http:\/\/juliangamble.com\/blog\/2012\/08\/03\/the-little-schemer-in-clojure-chapter-3\/\">built lists [Ch3]<\/a>. The bigger principle of the book is to be able to operate on data structures with a minimal set of primitives using the power of recursion and lambdas.<\/p>\n<p>Now we&#8217;re driving at the meta-circular interpreter with these principles. We also want to be able to do mathematical operations, and yet still keep a minimal number of primitives. Interestingly enough, we&#8217;ll just use <code>equals<\/code>, <code>add1<\/code> and <code>sub1<\/code> and build up to multiplication, division and exponents. So let&#8217;s get started!<\/p>\n<p>Our first function is <code>+_<\/code> (plus) &#8211; we&#8217;re going to define it terms of add1 and sub1. (We&#8217;ll rename the functions with an _ suffix so they don&#8217;t clash with the existing clojure definitions of <code>+<\/code> and <code>zero?<\/code><\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def zero_?\r\n  (fn &#x5B;n]\r\n    (= 0 n)))\r\n\r\n(def add1\r\n  (fn &#x5B;n]\r\n    (+ 1 n)))\r\n\r\n(def sub1\r\n  (fn &#x5B;n]\r\n    (- n 1)))\r\n\r\n(def +_\r\n  (fn &#x5B;n m]\r\n    (cond\r\n      (zero_? m) n\r\n      true (add1 (+ n (sub1 m))))))\r\n\r\n(println (+_ 1 2))\r\n<\/pre>\n<p>Now this is kind of frustrating. Why bother doing all this recursion for an operation that is already built into the CPU? Especially when you limit yourself to integers anyway?<\/p>\n<p>This is about making you think about numeric implementations. Part of it is that LISPs generally implement their own &#8216;numeric tower&#8217; &#8211; you can see what fresh thinking has done for Clojure&#8217;s ability to handle numbers &#8211; particularly irrational fractions.<\/p>\n<p>The other reason is the purity of the metacircular interpreter that you&#8217;ll build &#8211; you&#8217;ll literally be able to count the number of primitives required to build it and have no holes. (There is an assumption that recursion is cheap.)<\/p>\n<p>Our next function is &#8211; (minus) which is quite similar to the above:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def -_\r\n  (fn &#x5B;n m]\r\n    (cond\r\n      (zero_? m) n\r\n      true (sub1 (- n (sub1 m))))))\r\n\r\n(println (-_ 2 1))\r\n<\/pre>\n<p>From here we extend our concept of the <code>lat<\/code> (a List-ATom) &#8211; being a non-nested list of atoms. We extend it to what the book calls a <code>vec<\/code>, which is a non-nested list of integers.<\/p>\n<p>From here we arrive at [The Fourth Commandment]. This states When recurring on a list of atoms, <code>lat<\/code>, or a <code>vec<\/code>, ask two questions about them, and use <code>(cdr lat)<\/code> or <code>(cdr vec)<\/code> for the natural recursion.<\/p>\n<p>It then goes on to apply this to lists of numbers as well. It goes on: When recurring on a number, <code>n<\/code>, ask two questions, and use <code>(sub1 n)<\/code> for the natural recursion.<\/p>\n<p>Now we get to the <code>addvec<\/code> function. This is really like a <code>sum<\/code> function from sql land:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def addvec\r\n  (fn &#x5B;vec]\r\n    (cond\r\n      (empty? vec) 0\r\n      true (+_ (first vec) (addvec (rest vec))))))\r\n\r\n(println (addvec '(1 2 3)))\r\n<\/pre>\n<p>Next we look at the multiply function <code>*_<\/code>.<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def *_\r\n  (fn &#x5B;n m]\r\n    (cond\r\n      (zero_? m) 0\r\n      true (+_ n (*_ n (sub1 m))))))\r\n\r\n(println (*_ 4 5))\r\n<\/pre>\n<p>Again &#8211; we&#8217;ve built this in terms of our existing primitives.<\/p>\n<p>Now we get onto T<em>he Fifth Commandment<\/em>. I know these could come across as boring and self-righteous. On the other hand, if you write recursive code from scratch (and don&#8217;t rely on a library to do it for you) you want to have absolute confidence that it will run and terminate as you expect. These Commandments give you that confidence.<\/p>\n<p>The Fifth Commandment states: When building a value with <code>+_<\/code>\u00a0(plus), always use <code>0<\/code> for the value of the terminating line, for adding 0 does not change the value of an addition.<\/p>\n<p>It goes on to say: when building a value with <code>*_<\/code>(multiply), always use <code>1<\/code> for the value of the terminating line, for multiplying by 1 does not change the value of a multiplication.<\/p>\n<p>It then finishes with: when building a value with <code>cons<\/code>, always consider <code>()<\/code> for the value of the terminating line.<\/p>\n<p>Now we&#8217;ll look at <code>vec+<\/code>. The big idea is to be able to add two lists of numbers matching each corresponding element in the sum operation. This has uses in matrix operations:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def vec+\r\n  (fn &#x5B;vec1 vec2]\r\n    (cond\r\n      (empty? vec1) vec2\r\n      (empty? vec2) vec1\r\n      true (cons (+_ (first vec1) (first vec2))\r\n             (vec+\r\n               (rest vec1) (rest vec2))))))\r\n\r\n(println (vec+ '(1 2 3) '(4 5 6)))\r\n<\/pre>\n<p>Now we&#8217;ll look at <code>&gt;_<\/code>(greater than). We&#8217;ll define it in terms of our primitives.<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def &gt;_\r\n  (fn &#x5B;n m]\r\n    (cond\r\n      (zero_? n) false\r\n      (zero_? m) true\r\n      true (&gt;_ (sub1 n) (sub1 m)))))\r\n\r\n(println (&gt;_ 10 1))\r\n(println (&gt;_ 1 10))\r\n<\/pre>\n<p>We&#8217;ll reuse this for less-than. It actually turns out remarkably similar:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def &lt;_\r\n  (fn &#x5B;n m]\r\n    (cond\r\n      (zero_? m) false\r\n      (zero_? n) true\r\n      true (&lt;_ (sub1 n) (sub1 m)))))\r\n\r\n(println (&gt;_ 10 1))\r\n(println (&gt;_ 1 10))\r\n<\/pre>\n<p>Next we&#8217;ll define equals:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\"> \r\n(def =_   \r\n  (fn &#x5B;n m]     \r\n    (cond       \r\n      (&gt;_ n m) false\r\n      (&lt;_ n m) false      \r\n      true true)))\r\n\r\n(println &quot;=_&quot;)\r\n(println (=_ 1 10))\r\n(println (=_ 10 1))\r\n(println (=_ 10 10))\r\n<\/pre>\n<p>Next we&#8217;ll look at exponents:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def exp\r\n  (fn &#x5B;n m]\r\n    (cond\r\n      (zero_? m) 1\r\n      true (*_ n (exp n (sub1 m))))))\r\n\r\n(println (exp 2 3))\r\n<\/pre>\n<p>Now we&#8217;ll start using our numbers functions on atoms and lats &#8211; this gets used in our metacircular evaluator later. First we&#8217;ll start with length:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def length\r\n  (fn &#x5B;lat]\r\n    (cond\r\n      (empty? lat) 0\r\n      true (add1 (length (rest lat))))))\r\n\r\n(println (length '(pasta with pesto and mushrooms)))\r\n<\/pre>\n<p>Now we&#8217;re going to write a function <code>pick<\/code> to get an item out of a list using an index.<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def pick\r\n  (fn &#x5B;n lat]\r\n    (cond\r\n      (empty? lat) '()\r\n      (zero_? (sub1 n)) (first lat)\r\n      true (pick (sub1 n) (rest lat)))))\r\n\r\n(println (pick  3 '(pasta with pesto and mushrooms)))\r\n<\/pre>\n<p>Now we&#8217;re going to extend this to remove an indexed item from a list using <code>rempick<\/code>:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def rempick\r\n  (fn &#x5B;n lat]\r\n    (cond\r\n      (empty? lat) '()\r\n      (zero_? (sub1 n)) (rest lat)\r\n      true (cons (first lat)\r\n             (rempick\r\n               (sub1 n) (rest lat))))))\r\n\r\n(println (rempick  2 '(pasta with pesto and mushrooms)))\r\n<\/pre>\n<p>Now we&#8217;re going to write a function to strip all the numbers out of a list. We&#8217;ll cheat a little bit, as we&#8217;ll introduce a new primitive function <code>number?<\/code>. We&#8217;ll call our strip function <code>no-nums<\/code>.<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def no-nums\r\n  (fn &#x5B;lat]\r\n    (cond\r\n      (empty? lat) '()\r\n      true (cond\r\n             (number? (first lat)) (no-nums (rest lat))\r\n             true (cons (first lat)\r\n                    (no-nums (rest lat)))))))\r\n\r\n(println (no-nums  '(1 potato 2 potato 3 potato 4)))\r\n<\/pre>\n<p>This time we&#8217;ll flip it over &#8211; and write a function to strip out all the non-numbers from the list:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def all-nums\r\n  (fn &#x5B;lat]\r\n    (cond\r\n      (empty? lat) '()\r\n      true (cond\r\n             (number? (first lat)) (cons (first lat) (all-nums (rest lat)))\r\n             true (all-nums (rest lat))))))\r\n\r\n(println (all-nums  '(1 potato 2 potato 3 potato 4)))\r\n<\/pre>\n<p>Our final function <code>eqan?<\/code> is our first building block towards rewriting the equals function in terms of our own primitives. This function will get us about half way there:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def eqan?\r\n  (fn &#x5B;a1 a2]\r\n    (cond\r\n      (number? a1)\r\n        (cond\r\n          (number? a2) (=_ a1 a2)\r\n          true false)\r\n      (number? a2) false\r\n      true (= a1 a2))))\r\n\r\n(println (eqan?  1 10))\r\n(println (eqan?  10 1))\r\n(println (eqan?  10 10))\r\n(println (eqan?  'a 'b))\r\n(println (eqan?  'a 'a))\r\n<\/pre>\n<p><strong>Conclusion<\/strong><br \/>\nThis chapter we&#8217;ve introduced two new primtives <code>add1<\/code> and <code>sub1<\/code> &#8211; and used them along with all our existing primitives to build all the functions above.<\/p>\n<p>In total our primitives so far are: <code>atom?<\/code>, <code>null?<\/code>, <code>first<\/code>, <code>rest<\/code>, <code>cond<\/code>, <code>fn<\/code>, <code>def<\/code>, <code>empty?<\/code>, <code>=<\/code>, <code>cons<\/code>, <code>add1<\/code> and <code>sub1<\/code>. These are all the functions (and those in the chapters to come) that we&#8217;ll need to implement to get our metacircular interpreter working.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the fourth Chapter of a series of posts about porting\u00a0The Little Schemer\u00a0to Clojure. You may wish to\u00a0read the intro. You&#8217;ll notice that in the first three chapters, we introduced lists [Ch1], then we pulled things out of lists &hellip; <a href=\"https:\/\/juliangamble.com\/blog\/2012\/08\/10\/the-little-schemer-in-clojure-chapter-4-numbers-games\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[3,12],"tags":[],"class_list":["post-314","post","type-post","status-publish","format-standard","hentry","category-clojure","category-thelittleschemer"],"_links":{"self":[{"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/posts\/314","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/comments?post=314"}],"version-history":[{"count":18,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/posts\/314\/revisions"}],"predecessor-version":[{"id":569,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/posts\/314\/revisions\/569"}],"wp:attachment":[{"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/media?parent=314"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/categories?post=314"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/tags?post=314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}