# Modifying a List in a function in place [duplicate]

An example will be most specific:

func[list_, column_] := list[[All, column]] = Map[#*2 &, list[[All, column]]];


This throws errors.

I want to avoid doing something like this:

func2[list_] := Map[#*2 &; list];
list[[All, 2]] = func2[list[[All,2]]]


because nesting a couple of functions raises complexity unnecessarily, the output would have to be reassigned every time.

As a followup, using HoldFirst works fine, but using the so defined function in a Map gives again errors.

The setup is as follows:

create a nested list

testList = Table[Table[{x y, x y 2}, {x, 1,3}], {y,1,3}]


define afunc with HoldFirst Attribute

afunc = Function[{list, col}, list[[All, col]] = Map[# * 2 &, list[[All, col]]], HoldFirst]


and another function using the first

bfunc[nestedList_, col_] := Map[afunc[#, col] &, nestedList]


now, a call to

bfunc[testList, 2]


should alter the 2'nd columns of the nested lists I'd expect, but it instead throws errors

i've tried to set Attribute HoldFirst on this function as well but it didn't work out as expected

-

## marked as duplicate by Mr.Wizard♦Jan 13 '14 at 8:44

Well, with your follow-up, you really opened a can of worms. Without a very detailed discussion, here is a working version of your bfunc: ClearAll[bfunc]; SetAttributes[bfunc, HoldFirst]; bfunc[nestedList_, col_] := Table[With[{i = i}, afunc[nestedList[[i]], col]], {i, Length[nestedList]}]. Note that 1: You should have used patterns and HoldFirst for bfunc 2:the construction f[#]& is not the same as f,since it leaks evaluation during the parameter-passing in a pure function 3. Map is a wrong tool for the task, since there is no way with it to prevent evaluation of sub-parts. –  Leonid Shifrin Mar 28 '12 at 11:34
I want to add that generally, programming with the pass-by-reference style is a bit going against the idiomatic Mathematica, and so you should get a really good understanding of evaluation process if you don't want nasty surprises on every mile of this road. –  Leonid Shifrin Mar 28 '12 at 11:38
Thanks for your comments. I'm having a quite strong background in OOP and procedural programming languages, the functional approach is making me troubles though, but I think I'm not alone. –  phil Mar 28 '12 at 11:48
Note also that Mathematica is not really a functional language at its core - it emulates functional paradigm (quite well), but its core is term-rewriting. Many of the issues here are specific to Mathematica, for example quite complex evaluation control, or patterns. If you are interested in FP in Mathematica specifically, you may check out my book, which is heavily centered around an FP paradigm. It does not however explain evaluation in great detail. –  Leonid Shifrin Mar 28 '12 at 11:52
@Leonid, what do you mean by "... there is no way with it to prevent evaluation of sub-parts"? –  Mr.Wizard Mar 28 '12 at 11:57

You basically need a pass-by-reference semantics, which in Mathematica can be emulated with Hold-attributes. Add a HoldFirst attribute to your function:

SetAttributes[func,HoldFirst]


and you should be fine. Without it, list evaluates to its value before the assignment is attempted, and since expressions in Mathematica are immutable, you get an error.

func = Function[{list,column},
list[[All, column]] = Map[#*2 &, list[[All, column]]],
HoldFirst
]


Note however that, since this is a pure function, you can not do argument checks as elegantly as you can with patterns, and you can not overload your functions on different arguments as elegantly.

Note also that, while yet another way to do this is to keep your function as it is but rather wrap the first argument in Unevaluated in every function call, I would strongly advise against that. The reason is that it makes the function itself not self-contained, because it has to assume that the user will always remember to use Unevaluated (which it shouldn't), and there is no way to test whether or not the user actually did use it.

-
is there a one liner to do that in the function definition directly? –  phil Mar 28 '12 at 10:41
@phil Yes, see my edit. –  Leonid Shifrin Mar 28 '12 at 10:44
Hey, I´m counting four lines ;-) –  Yves Klett Mar 28 '12 at 11:02
@Yves That only depends on the magnification of the Mathematica notebook :) –  Leonid Shifrin Mar 28 '12 at 11:03
Philosophically I'm curious as to the motivation for doing this. It seems to re-introduce state. If the list needs to evolve, couldn't that be achieved with Nest or Fold ? –  image_doctor Mar 28 '12 at 11:39