I haven't seen this question specifically addressed before in this site, although some hints and traces have been given, for instance, here:
Does pass-by-value affect the performance of function calls?
Working with large data, pass-by-reference, compiled functions
Passing lists to functions in a manner that works like pass-by-reference in other languages?
So, my question is: How can/should I specify which arguments of a given user-defined function have to be treated as passed by reference or by value? Preferably, this should be done in the definition of the function. Clear reliable instructions are also desirable.
I want to pass some variables by reference to a function, because I want the function to modify the value of that variable (i.e., the function has to act or work on that variable, and not on a local copy of that variable that would vanish when the function ends). I do not feel comfortable using 'global variables' (which is the default scope for any variable in Mathematica, as far as I understand). I prefer to apply a classic approach: any variable or 'element' that is going to be either used or modified by a function, has to be 'passed' to that function via its argument list, either by reference or by value. In this way, I can better monitor what is happening and less unexpected interactions or behaviours can occur (of course, this reasoning is nothing new to all those who usually program in languages such of C, etc.).
I have already read something about using Hold
, Unevaluated
, etc. I am just posing this question to have it specifically addressed and treated in this Q&A forum, so that complete general answers can be given.
If this specific subject is already addressed elsewhere, I would appreciate to be informed about.
As a MWE, I can give this:
myfunc[a_, b_] := {
a = 2*a;
b = -b;
};
vara = 5;
varb = 6;
myfunc[vara, varb];
{vara, varb}
Actually, it is an incomplete NOT working example. In this example, I would like
a
to be treated as a passed-by-reference variable (so thatvara
should be actually changed at the end of the main routine), whileb
being treated as a passed-by-value variable (so thatb = -b
should not have any actual influence on the value ofvarb
).
How can I specify this in Mathematica?
Currently, this example returns the following errors: "Set: Cannot assign to raw object 5" and "Set: Cannot assign to raw object 6" because the function is trying to modify something which is interpreted by Mathematica as a constant, not a variable (I mean the function is getting raw numbers 5 and 6 as inputs, I guess).
BONUS: How does it affect to the result the fact that the variables being involved are defined either with =
or :=
? I guess =
should preferably be used when dealing with variables that are expected to contain values (temporary results of partial computations, generally speaking), and :=
for defining functions and so on.
Hold*
attribute and pass the variable name. $\endgroup$ – Szabolcs Sep 22 '17 at 8:10Hold
is a general solution that works in all cases, or whether there are some issues to have into account (I mean,Hold
has many different uses; it was not meant to be created just to deal with pass-by-reference variables). $\endgroup$ – Vicent Sep 22 '17 at 8:14