Group Abstract Group Abstract

Message Boards Message Boards

Passing variables by reference

GROUPS:
In C and other languages, I can pass a variable to a function by value or by reference. If, for example, I pass an array by reference, I can act on the array in place without creating a new cooy to return.

I see no easy way to do this in Mathematica.

Can this be done, and if so, how?

Thanks.
POSTED BY: George Woodrow III
Answer
11 months ago
Have a look at Attempting to make an assignment to the argument of a function over at stackexchange.

In short, you're looking for Hold
Attributes[modifyInPlace]={HoldAll};
modifyInPlace[arr_]:=(arr[[1]]=9)
a={1,1,1,1};
modifyInPlace[a];

a
(* a is now {9, 1, 1, 1} *)
POSTED BY: Simon Schmidt
Answer
11 months ago
Thanks. I'll check it out. My real function has several parameters, and has a return value. I'm assuming that HoldFirst will work if I only want to pass the first parameter by reference.

It strikes me, though, that this construct is not good Mathematica practice.
POSTED BY: George Woodrow III
Answer
11 months ago
Using HoldAll is generally perfectly fine in practice. What is more likely to be bad practice is the creation of a function like "modifyInPlace" which modifies its input. In pure functional programming languages, this is not allowed.

Your question is very common for anyone coming from  a language like C/C++ to Java/Python/Haskell/Mathematica etc. Many worry that if they aren't passing a reference to a function, then they are being inefficient because in C/C++ that would mean they were copying. This isn't the case with these other languages. 

Typically what you'll want to do is write a function that takes in a list and, instead of modifying the list that was given to it, returns a new list that is an updated version of the previous list. I understand that coming from a C/C++ background this likely sounds insane and horribly inefficient, but it allows you to write pure functions which are easier to test and maintain. 
POSTED BY: Sean Clarke
Answer
11 months ago
For many purposes the use of HoldXXX attributes is perfectly sensible. If you really need to do this in a way that emulates pointers,  might get some ideas from

http://stackoverflow.com/questions/6691491/implementing-a-quadtree-in-mathematica
POSTED BY: Daniel Lichtblau
Answer
11 months ago
Thanks for the suggestions. I have taken a look at the code, and it offers some ideas.

I am in the process of rewriting some ancient (ca 1972) BASIC code, and my first inclination is to imitate the BASIC paradigm as much as is needed to do a port. I could have done a lin-by-line translation -- Mathematica has a GOTO construct, after all -- but my aim is to master tbhe Mathematica way. What I will end up with is not going to be a one-to-one transformation, but I wil (finally) master the Mathematica way.

I already use the paradigm of returning a new list, and I have learned not to worry about what goes on under the hood. What I need to do is to adjust the logic so that the code does not depend on side effects from executing a function. Tricky, in the case of ancient BASIC, but do-able.

I begin to understand the contention that BASIC ruins people for real programming. At the time, however, it was BASIC or FORTRAN (c had not been invented), and my primary job was a research biochemist, so FORTRAN was a bit more than I needed for the type of computatins I needed to do.

Fortunately, I do not have to worry about fitting everythng into 8K of address space.
POSTED BY: George Woodrow III
Answer
11 months ago
My first BASIC code was also written in 1972, possibly a few towns away from you if memory serves. C was apparently under development at that time but had not yet escaped the Labs.
POSTED BY: Daniel Lichtblau
Answer
11 months ago
Thanks for all your help. I have some sample code:
 Dynamic[entE1]
 
 Dynamic[entS1]
 
 entE1 = 3000;
 entS1 = 0;
 
 SetAttributes[setEnergy, HoldAll]
 
setEnergy[x_, entE_, entShields_] :=
Module[{newE = entE, newS = entShields, tot},
  tot = entE + entShields;
  newE = (1 - x)*tot;
  newS = x * tot;
 
  (*
      executing these lines updated variables passed.
  numbers are passed, we get an error
  *)
  entE = newE;
  entShields = newS;
 
  Style[StringForm[
    "percentage is is : `` \r Ent Energy is ``\r shields: ``",
    NumberForm[x, 4], NumberForm[newE, 4], NumberForm[newS, 4]], 12,
   Blue, FontFamily -> "Courier New"]]

val2FromSlider[myX_] := Module[{limits}, limits = 1;
  Slider[myX, {0, limits}]]

showValue[x_] :=
Style[StringForm["value is : `` ",
   NumberForm[x, 4, NumberSigns -> {"-", "+"}]], 12, Blue,
  FontFamily -> "Courier New"]

{val2FromSlider[Dynamic[eEn]], showValue[Dynamic[eEn]],
Dynamic[setEnergy[eEn, entE1, entS1]], Dynamic[entE1],
Dynamic[entS1]}

This is a toy example of what I want to do. There are separate functions. One does the UI part, using a slider to set a percentage. There is a function that uses the current values of entE1 and entS1 to cumpute new values of the variables using the percentage eEn.  The display code in setEnergy[] is there for debugging purposes.

This code works as written.

I tried to have setEnergy[] return the new values of entE1 and entS1, but if I did so, they were not dynamically updated. I tried wrapping Dynamic around the returned variables, to no avail. (I thought that this approach would work.)

I tried some other variations without much success.

As I said, this version works, and I can apply it to my real code. I would like to know if there is a more elegant solution.

Thanks.
POSTED BY: George Woodrow III
Answer
11 months ago