{"id":328,"date":"2012-08-17T21:21:37","date_gmt":"2012-08-17T11:21:37","guid":{"rendered":"http:\/\/juliangamble.com\/blog\/?p=328"},"modified":"2013-12-27T10:35:18","modified_gmt":"2013-12-26T23:35:18","slug":"the-little-schemer-in-clojure-chapter-5-the-multichapter-chapter","status":"publish","type":"post","link":"https:\/\/juliangamble.com\/blog\/2012\/08\/17\/the-little-schemer-in-clojure-chapter-5-the-multichapter-chapter\/","title":{"rendered":"The Little Schemer in Clojure &#8211; Chapter 5 &#8211; The Multichapter Chapter"},"content":{"rendered":"<p><em>This is the fifth 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>Ok &#8211; so far we&#8217;ve <a href=\"http:\/\/juliangamble.com\/blog\/2012\/07\/20\/the-little-schemer-in-clojure-chapter-1\/\">introduced lists [Ch1]<\/a>, we&#8217;ve <a href=\"http:\/\/juliangamble.com\/blog\/2012\/07\/29\/the-little-schemer-in-clojure-chapter-2\/\">pulled things out of lists [Ch2]<\/a>, we&#8217;ve <a href=\"http:\/\/juliangamble.com\/blog\/2012\/08\/03\/the-little-schemer-in-clojure-chapter-3\/\">built lists [Ch3]<\/a>\u00a0and we&#8217;ve <a href=\"http:\/\/juliangamble.com\/blog\/2012\/08\/10\/the-little-schemer-in-clojure-chapter-4-numbers-games\/\">assembled a minimal numeric tower[Ch4]<\/a>. The assumption behind all of these was that we were only reading or making one change at a time. This time we&#8217;ll extend our capabilities to handle multiple items. To put it another way &#8211; this chapter is all about the &#8216;find all&#8217; and the &#8216;replace all&#8217;.<\/p>\n<p>We&#8217;ll start with some revision &#8211; we&#8217;ll go back to our old friend <code>member<\/code>.<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def member?\r\n  (fn &#x5B;a lat]\r\n    (cond\r\n      (null? lat) false\r\n      true (or\r\n        (= (first lat) a)\r\n        (member? a (rest lat)))) ))\r\n\r\n(println (member? 'sweet '(potato wedges with sweet chilli sauce))) ; \/\/=&gt; true\r\n(println (member? 'sweet '(potato wedges with sweet sweet chilli sauce))) ; \/\/=&gt; true\r\n<\/pre>\n<p>Now the particular point we&#8217;re looking at now is that this function will stop at the first occurrence of <code>a<\/code> in <code>lat<\/code>. Now we&#8217;ll go back to another old friend <code>rember<\/code>.<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def rember\r\n  (fn &#x5B; a lat]\r\n    (cond\r\n      (null? lat) '()\r\n      true (cond\r\n        (= (first lat) a) (rest lat)\r\n        true (cons (first lat)\r\n          (rember\r\n            a (rest lat)))))))\r\n\r\n(println (rember 'banana '(apple banana orange))) ; \/\/=&gt; (apple orange)\r\n(println (rember 'banana '(apple banana banana orange))); \/\/=&gt; (apple banana orange)\r\n<\/pre>\n<p>Again &#8211; the point was that only the first occurrence is dealt with &#8211; this chapter is about how we will to address that. So let&#8217;s start with <code>multirember<\/code>:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def multirember\r\n  (fn &#x5B;a lat]\r\n    (cond\r\n      (null? lat) '()\r\n      true (cond\r\n             (= (first lat) a) (multirember a (rest lat))\r\n             true (cons (first lat) (multirember a (rest lat)))))))\r\n\r\n(println (multirember 'sweet '(potato wedges with sweet sweet chilli sauce))); \/\/=&gt; (potato wedges with chilli sauce)\r\n<\/pre>\n<p>The main difference is that we keep calling the function until the end of the lat, even if the result is found.<\/p>\n<p>Now let&#8217;s do <code>multiinsertR<\/code>:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def multiinsertR\r\n  (fn &#x5B;new old lat]\r\n    (cond\r\n      (null? lat) '()\r\n      true (cond\r\n             (= (first lat) old) (cons (first lat) (cons new (multiinsertR new old (rest lat))))\r\n             true (cons (first lat) (multiinsertR new old (rest lat)))))))\r\n\r\n(println (multiinsertR 'hot 'with '(with potato wedges with chilli sauce))); \/\/=&gt; (with hot potato wedges with hot chilli sauce)\r\n<\/pre>\n<p>Too easy! Now let&#8217;s do <code>multiinsertL<\/code>:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def multiinsertL\r\n  (fn &#x5B;new old lat]\r\n    (cond\r\n      (null? lat) '()\r\n      true (cond\r\n             (= (first lat) old) (cons new (cons old (multiinsertL new old (rest lat))))\r\n             true (cons (first lat) (multiinsertL new old (rest lat)))))))\r\n\r\n(println (multiinsertL 'with 'hot '(hot potato wedges hot chilli sauce))); \/\/=&gt; (with hot potato wedges with hot chilli sauce)\r\n<\/pre>\n<p>So a pattern is developing here &#8211; which means it&#8217;s time for another Commandment. Here Goes. The Sixth commandment states that you Always change at least one argument while recurring. The changing argument(s) should be tested in the termination condition(s) and it should be changed to be closer to termination. For example:<br \/>\nwhen using <code>rest<\/code>, test termination with <code>empty?<\/code><br \/>\nwhen using <code>sub1<\/code>, test termination with <code>zero?<\/code><\/p>\n<p>Ok &#8211; so apart from knowing the principles to have confidence in writing recursive code in the future &#8211; why else is this relevant? It&#8217;s important for building more complex data structures. One of Clojure&#8217;s key strengths is that it has lazy functional data structures. Clojure&#8217;s data structures are built around this idea of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Hash_array_mapped_trie\">hash-trie<\/a>. It&#8217;s the idea that you can modify a tree structure that is still immutable and performant. The point being &#8211; you need to start building blocks for how you think about data structures.<\/p>\n<p>Now we&#8217;re going to look at <code>multisubst<\/code>:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def multisubst\r\n  (fn &#x5B;new old lat]\r\n    (cond\r\n      (null? lat) '()\r\n      true (cond\r\n             (= (first lat) old) (cons new (multisubst new old (rest lat)))\r\n             true (cons (first lat) (multisubst new old (rest lat)))))))\r\n\r\n(println (multisubst 'hot 'sweet '(sweet potato wedges with sweet chilli sauce))); \/\/=&gt; (hot potato wedges with hot chilli sauce)\r\n<\/pre>\n<p>Now we&#8217;re going to do <code>occur<\/code> which is a bit like the aggregate <code>count<\/code> function in sql.<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def occur\r\n  (fn &#x5B;a lat]\r\n    (cond\r\n      (null? lat) 0\r\n      true (cond\r\n             (= (first lat) a) (add1 (occur a (rest lat)))\r\n             true (occur a (rest lat))))))\r\n\r\n(println (occur 'hot '(potato wedges with hot hot hot chilli sauce))); \/\/=&gt; 3\r\n<\/pre>\n<p>This chapter ends strangely &#8211; we digress into an optimisation of the <code>rempick<\/code> function by adding a new primitive <code>one?<\/code>:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(def one?\r\n  (fn &#x5B;n]\r\n    (= n 1)))\r\n\r\n(def rempick\r\n  (fn &#x5B;n lat]\r\n    (cond\r\n      (null? lat) '()\r\n      (one? n) (rest lat)\r\n      true (cons (first lat) (rempick (sub1 n) (rest lat))))))\r\n\r\n(println (rempick 4 '(potato wedges with hot chilli sauce))); \/\/=&gt; (potato wedges with chilli sauce)\r\n\r\n<\/pre>\n<p>You can see it running <a href=\"http:\/\/ideone.com\/30QIY\">here<\/a>.<\/p>\n<p><strong>Conclusion<\/strong><br \/>\nHere we&#8217;ve adapted our existing functions to be able to work for multiple occurrences of the search result. We&#8217;ve added one new primitive function: <code>one?\u00a0<\/code><\/p>\n<p>In total our primitives so far are:\u00a0<code>atom?<\/code>,\u00a0<code>null?<\/code>,\u00a0<code>first<\/code>,\u00a0<code>rest<\/code>,\u00a0<code>cond<\/code>,\u00a0<code>fn<\/code>,\u00a0<code>def<\/code>,\u00a0<code>empty?<\/code>,<code>=<\/code>,\u00a0<code>cons<\/code>,\u00a0<code>add1,<\/code>\u00a0<code>sub1<\/code> and <code>one?<\/code>. These are all the functions (and those in the chapters to come) that we\u2019ll need to implement to get our metacircular interpreter working.<\/p>\n<p><strong>Bringing it Back to Clojure<\/strong><\/p>\n<p>So how do we do a <code>multirember<\/code> in Clojure normally? Here is <a href=\"http:\/\/stackoverflow.com\/a\/941093\/15441\">an online example<\/a>:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(remove #{:foo} #{:foo :bar})      ;\/\/ =&gt; (:bar)\r\n(remove #{:foo} &#x5B;:foo :bar])       ;\/\/ =&gt; (:bar)\r\n(remove #{:foo} (list :foo :bar))  ;\/\/ =&gt; (:bar)\r\n<\/pre>\n<p>Other functions that apply to other data structures to consider:<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(disj #{:foo :bar} :foo)       ;\/\/ =&gt; #{:bar}\r\n(dissoc {:foo 1 :bar 2} :foo)  ;\/\/ =&gt; {:bar 2}\r\n(pop &#x5B;:bar :foo])              ;\/\/ =&gt; &#x5B;:bar]\r\n(pop (list :foo :bar))         ;\/\/ =&gt; (:bar)\r\n<\/pre>\n<p>So how is <code>remove<\/code> <a href=\"http:\/\/clojuredocs.org\/clojure_core\/1.3.0\/clojure.core\/remove\">implemented in Clojure<\/a>?<\/p>\n<pre class=\"brush: clojure; title: ; notranslate\" title=\"\">\r\n(defn remove\r\n  &#x5B;pred coll]\r\n  (filter (complement pred) coll))\r\n<\/pre>\n<p>This is more concise &#8211; but requires knowledge of the <code>filter<\/code> and <code>complement<\/code> functions &#8211; which we&#8217;ve chosen to exclude to keep a simple set of primitives.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the fifth Chapter of a series of posts about porting\u00a0The Little Schemer\u00a0to Clojure. You may wish to\u00a0read the intro. Ok &#8211; so far we&#8217;ve introduced lists [Ch1], we&#8217;ve pulled things out of lists [Ch2], we&#8217;ve built lists [Ch3]\u00a0and &hellip; <a href=\"https:\/\/juliangamble.com\/blog\/2012\/08\/17\/the-little-schemer-in-clojure-chapter-5-the-multichapter-chapter\/\">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-328","post","type-post","status-publish","format-standard","hentry","category-clojure","category-thelittleschemer"],"_links":{"self":[{"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/posts\/328","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=328"}],"version-history":[{"count":26,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/posts\/328\/revisions"}],"predecessor-version":[{"id":570,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/posts\/328\/revisions\/570"}],"wp:attachment":[{"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/media?parent=328"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/categories?post=328"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/juliangamble.com\/blog\/wp-json\/wp\/v2\/tags?post=328"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}