# Thread over a nested list top to bottom until non-list elements are found

I have a nested list:

list = {1, 2, {3, 4}, f[a], {2, h[b]}}


I would like to apply a function g to all elements of the nested list (starting from top to bottom) that are not lists themselves. That is, I would like to obtain:

{g[1], g[2], {g[3], g[4]},  g[f[a]], {g[2], g[h[b]]}}


(Using Map[g, list, {-1}] does not work, as it maps g inside f and h)

The alternative I have ended up using is the following function:

mapAtLeavesOfList[g_, x_List] := Map[mapAtLeavesOfList[g, #] &, x]
mapAtLeavesOfList[g_, x_] := g[x]

mapAtLeavesOfList[g, list]
=> {g[1], g[2], {g[3], g[4]}, g[f[a]], {g[2], g[h[b]]}}


Any better suggestions?

-
This feels like a duplicate to me. Does anyone know what I may be remembering? –  Mr.Wizard Jan 5 '13 at 4:07

Contrary to what the title claims, your example shows that do not want to map at the "maximum depth" of the list, but rather, merely onto the elements of a List that are not lists themselves. I think you're over complicating things with your definition of mapAtLeavesOfList.

The solution is as simple as:

Clear@g
g[a_List] := g /@ a

g@list
(* {g[1], g[2], {g[3], g[4]}, g[f[a]], {g[2], g[h[b]]}} *)


If you want to use g as a blackbox function, the following should work:

Block[{mapg},
mapg[a_List] := mapg /@ a;
mapg@list /. mapg -> g
]


or even:

Block[{g},
g[a_List] := g /@ a;
g@list
]


The above solution temporarily modifies g to make it listable using Block and once outside the Block, the original definition of g kicks in.

You can also set the Listable attribute for g as in Leonid's answer.

-
In the spirit of your last suggestion, one could also do something like Block[{g}, g[list] //. x_g :> Thread[x]] –  Leonid Shifrin Jan 5 '13 at 1:19
Thanks. I have changed the title to better reflect the question. –  ecoxlinux Jan 5 '13 at 1:28
@ecoxlinux But the title still misses the point - what you ask is not mapping on leaves, you rather ask to thread over the lists top to bottom until non-lists are encountered. –  Leonid Shifrin Jan 5 '13 at 1:34
Thanks to both of you (leonid and hypnotoad). Hypnotoad, I was indeed overcomplicating the issue. –  ecoxlinux Jan 5 '13 at 2:49

A few other alternatives: either you can make g itself a Listable function by executing SetAttributes[g,Listable] (assuming that g is a symbol), or you can do something like this:

Function[Null, g[#], Listable][list]


where I don't make any assumptions on g (which may be a symbol but may be something else).

Note that there are subtle differences between setting g Listable and defining g[a_List] := g /@ a. The latter method is less general in two respects. First, you may not be able to add a new definition, for whatever reason. Second, this won't work if g carries Hold - attributes (HoldAll or HoldFirst) - because they will prevent the pattern g[a_List] from matching, if you pass a variable such as list. The methods based on Listable attribute are free from this particular limitation.

-
@Rojo Yes, you are right. Will edit. –  Leonid Shifrin Jan 5 '13 at 21:28