# Recursively turn expression into nested list

I've been trying to write a simple function that turns an expression into a nested list. So for example, a+2b+3c becomes {a,{2,b},{3,c}}. This is what I wrote:

toList[x_] := Module[{},
x = List@@x;
For[i=1, i <= Length[x]; i++,
If[x[[i]] != List@@x[[i]], x[[i]] = toList[x[[i]]]]
];
x
]


However, I keep getting errors like "Tag Plus in a+2b+3c is protected" and "a+2b+3c in the part assignment is not symbol." How can I fix what's going wrong?

The following does what you want:

Apply[List, a + 2 b + 3 c, All]


This simply applies List to all parts of the expression in one go.

Alternatively:

Replace[a + 2 b + 3 c, _[args___] :> {args}, All]
(* {a, {2, b}, {3, c}} *)


The idea here is to replace the head of any expression with List. Note that Replace[…,…,All] is not equivalent to ReplaceAll[…,…] (i.e. …/.…). The former replaces from the inside out, while the latter from the outside in (and ignores parts that have already been touched)

As to why your attempt doesn't work:

• Function arguments are not variables (as in their value can't be modified). This is the reason for the "Tag … is protected" errors. To fix this, copy the value to a local variable
• For does not localize the iteration variable, so i is shared across recursive calls. To fix this, localize i explicitly.
• Equal/Unequal (==/!=) is for value equality, and doesn't evaluate in many cases (e.g. a==1 is not False). To do structural comparisons, use SameQ/UnsameQ (===/=!=).

Changing only what's necessary in your code yields the following working version:

toList[y_] := Module[
{x = y, i},
x = List @@ x;
For[i = 1, i <= Length[x], i++,
If[x[[i]] =!= List @@ x[[i]],
x[[i]] = toList[x[[i]]]
]
];
x
]

toList[a + 2 b + 3 c]
(* {a, 2 b, 3 c} *)


Further simplifications could be:

• Replace the For loop with Do (which does localize the variable)

toList[y_] := Module[
{x = y},
x = List @@ x;
Do[
If[x[[i]] =!= List @@ x[[i]],
x[[i]] = toList[x[[i]]]
],
{i, Length@x}
];
x
]

• Replace the For/Do loop with Map (the If now needs to return something in both cases, as the output is used):

toList[y_] := Module[
{x = y},
x = List @@ x;
x = Map[
If[# =!= List @@ #,
toList[#],
#
] &,
x
];
x
]

• Remove the unnecessary local variable x:

toList[y_] := Map[
If[# =!= List @@ #,
toList[#],
#
] &,
List @@ y
]

• Move the termination condition for the recursion into the function definition itself using Condition (/;):

toList[y_] /; y =!= List @@ y := Map[
toList[#] &,
List @@ y
]
toList[y_] := y

• Use shorthands for Map (/@):

toList[y_] /; y =!= List @@ y := toList /@ List @@ y
toList[y_] := y

• Remove the termination condition completely (it's not needed, as Map/Apply don't do anything on expressions that have "zero length" (i.e. atoms)

toList[y_] := toList /@ List @@ y

• Yes, it is a matter of replacement of heads. – Αλέξανδρος Ζεγγ Sep 2 '18 at 14:10
• Wow, thanks! That is a really detailed explanation – Paradox Sep 2 '18 at 14:22
expr = a + 2 b + 3 (4 E^x + 3 x);

ReplaceRepeated[expr, f_[args___] /; (TrueQ[f =!= List]) :> List[args]]

(* {a, {2, b}, {3, {{4, {E, x}}, {3, x}}}} *)