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

Luke: 2 days ago

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?

Alexander: 2 days ago

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:

g[a_List] := g /@ a

(* {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:

    mapg[a_List] := mapg /@ a;
    mapg@list /. mapg -> g

or even:

    g[a_List] := g /@ a;

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.