Recursive list contruction - Mathematica Stack Exchange most recent 30 from mathematica.stackexchange.com 2019-10-17T04:22:09Z https://mathematica.stackexchange.com/feeds/question/91167 https://creativecommons.org/licenses/by-sa/4.0/rdf https://mathematica.stackexchange.com/q/91167 4 Recursive list contruction Rick R https://mathematica.stackexchange.com/users/9572 2015-08-08T21:37:10Z 2015-08-09T02:38:23Z <p>I am attempting to implement the exercises from The Little Schemer in Mathematica, and running to a bit of a challenge with rember (remove member). Given a list and a value, the function just returns the list with occurrences of value removed.</p> <pre><code>rember[a_, lat_] := Return[ If[NullQ[lat], Return[lat] , If[a == First[lat], Return[rember[a, Rest[lat]]], Return[Cons[First[lat], rember[a, Rest[lat]]]] ] ] ] </code></pre> <p>I created the helper functions NullQ and Cons based on The Little Schemer as well, with NullQ being true/false if a list is Null, and Cons being a wrapper around Prepend:</p> <pre><code>Cons[a_, lst_] := If[x === Null, Return[{a}], Return[Prepend[lst, a]]] NullQ[x_] := If[ListQ[x], If[Length[x] == 0, Return[True], Return[False]] , Return[False] ]; </code></pre> <p>The idea in rember is if it's Null, the recursion ends, otherwise it checks the first item of the list, if that's a match it calls remember with the remainder of the list, if it's not a match it prepends that value onto calling rember with the remainder of the list.</p> <p>I think my logic is correct, but returns are not working correctly. How do I construct this list recursively? I'm sure my code is bad on several levels, thank you in advance for any advice you have.</p> <p>EDIT: corrected code to not return a serially.</p> https://mathematica.stackexchange.com/questions/91167/-/91173#91173 7 Answer by halirutan for Recursive list contruction halirutan https://mathematica.stackexchange.com/users/187 2015-08-08T23:26:12Z 2015-08-09T02:38:23Z <p>Please read carefully <a href="https://mathematica.stackexchange.com/questions/24988/can-one-identify-the-design-patterns-of-mathematica/25474#25474">the post</a> that Leonid referred to. Let me anyway give you some tips on your code. First, <code>Return</code> does work differently in <em>Mathematica</em> than you might would expect. You can use <code>Return</code> to return from functions or loops like this one</p> <pre><code>Do[ If[x == 5, Return[True]], {x, 10} ] </code></pre> <p>What you did is to nest it which doesn't work like you expect it. Here is a simple example that shows the mistake</p> <pre><code>abs[x_] := Return[If[x &gt; 0, Return[x], Return[-x]]] abs (* Return *) </code></pre> <p>The question is, why use it at all? It is not required. When you call a function, <em>Mathematica</em> will happily return the last expression. That means, you don't need it at all (your <code>Cons</code> line prepended the wrong element, <code>x === Null</code> in <code>Cons</code> doesn't make sense, ...). Here is a slightly fixed version of your original approach:</p> <pre><code>Cons[a_, lst_List] := Prepend[lst, a]; NullQ[{}] = True; NullQ[___] := False; rember[a_, lat_] := If[NullQ[lat], lat, If[a == First[lat], rember[a, Rest[lat]], Cons[First[lat], rember[a, Rest[lat]]]] ] rember[5, Range] (* {1, 2, 3, 4, 6, 7, 8, 9, 10} *) </code></pre> <p>Let me give you a different method. It uses a nested list structure that is built up inside of a recursive function (don't forget to <code>ClearAll[rember]</code> first):</p> <pre><code>rember[a_, l_] := Flatten[r[a, l, {}]]; r[_, {}, out_] := out; r[a_, {a_, rest___}, out_] := r[a, {rest}, out]; r[a_, {start_, rest___}, out_] := r[a, {rest}, {out, start}] </code></pre> <p>The <code>rember</code> function here acts only as a wrapper to call the core function <code>r</code> that does the job. When the <a href="https://stackoverflow.com/q/4481301/1078614">tail recursive</a> function <code>r</code> has done its job, the resulting nested list needs to be flattened.</p>