Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

This question already has an answer here:

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.

Thanks in advance.

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

share

marked as duplicate by Mr.Wizard Jan 13 at 8:44

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2  
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

1 Answer 1

up vote 11 down vote accepted

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.

To address your question in comments, the one-liner you asked for can be this:

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.

share
    
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
1  
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

This site is currently not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .