Skip to main content
added 1085 characters in body
Source Link
Nasser
  • 150.4k
  • 12
  • 161
  • 374

update 11/17/13:

Added this example from Wagner book, on the danger of using HoldAll. This is a good reason why one should stick to default pass-by-value in Mathematica. Here is the example:

ClearAll[p, inc, double, x];
SetAttributes[inc, HoldAll];
SetAttributes[double, HoldFirst];
inc[x_] := x = x + 1;
double[x_] := x + x
p = 4;
inc[p];   (* this makes p=5 now *)
double[p] (* this makes p=10 now *)

gives as expected :

(*  10  *)

Now changing the call to emulate call by reference, and look what happens now:

ClearAll[p, inc, double, x];
SetAttributes[inc, HoldAll];
SetAttributes[double, HoldFirst];
inc[x_] := x = x + 1;
double[x_] := x + x
p = 4;
double[inc[p]]  (* what do you think p will be after this? *)

Gives

(* 11 *)

Clearly what happens, as the book says, is that in the second case, inc[p] was evaluated twice, and not one time as one would expect.

Hence inc[p]; double[p]; gave different result to double[inc[p]].

Original answer

update 11/17/13:

Added this example from Wagner book, on the danger of using HoldAll. This is a good reason why one should stick to default pass-by-value in Mathematica. Here is the example:

ClearAll[p, inc, double, x];
SetAttributes[inc, HoldAll];
SetAttributes[double, HoldFirst];
inc[x_] := x = x + 1;
double[x_] := x + x
p = 4;
inc[p];   (* this makes p=5 now *)
double[p] (* this makes p=10 now *)

gives as expected :

(*  10  *)

Now changing the call to emulate call by reference, and look what happens now:

ClearAll[p, inc, double, x];
SetAttributes[inc, HoldAll];
SetAttributes[double, HoldFirst];
inc[x_] := x = x + 1;
double[x_] := x + x
p = 4;
double[inc[p]]  (* what do you think p will be after this? *)

Gives

(* 11 *)

Clearly what happens, as the book says, is that in the second case, inc[p] was evaluated twice, and not one time as one would expect.

Hence inc[p]; double[p]; gave different result to double[inc[p]].

Original answer

added 322 characters in body
Source Link
Nasser
  • 150.4k
  • 12
  • 161
  • 374
flip[1, 1, Unevaluated[s]]Unevaluated[s]];
s
(*  {{-1, 1, 1, -1}, {1, 1, -1, -1}, {-1, -1, 1, -1}, {-1, 1, -1, 1}}  *)
ClearAll[flip];
flip[posX_, posY_, lattice_] := 
  Module[{x = posX, y = posY}, 
   lattice = 
    ReplacePart[lattice, {y, x} -> -valueAtPos[x, y, lattice]] //. {{1} :> 
       1, {-1} :> -1}
   ];
Attributes[flip] = {HoldAll};HoldAll;
valueAtPos[positionX_, positionY_, lattice_List] := 
 Flatten[Take[lattice, {positionY, positionY}, {positionX, positionX}]]
s = {{1, 1, 1, -1}, {1, 1, -1, -1}, {-1, -1, 1, -1}, {-1, 1, -1, 1}};

But I think, in the spirit of Mathematica programming and functional programming, is that one should not do these things. i.e. functions should not have side-effects. To modify something, write newValue = foo[ oldValue ] and pass things by value, which is the default.

see also passing-large-list-by-reference and does-pass-by-value-affect-the-performance-of-function-calls

flip[1, 1, Unevaluated[s]]
s
(*  {{-1, 1, 1, -1}, {1, 1, -1, -1}, {-1, -1, 1, -1}, {-1, 1, -1, 1}}  *)
ClearAll[flip];
flip[posX_, posY_, lattice_] := 
  Module[{x = posX, y = posY}, 
   lattice = 
    ReplacePart[lattice, {y, x} -> -valueAtPos[x, y, lattice]] //. {{1} :> 
       1, {-1} :> -1}
   ];
Attributes[flip] = {HoldAll};
valueAtPos[positionX_, positionY_, lattice_List] := 
 Flatten[Take[lattice, {positionY, positionY}, {positionX, positionX}]]
s = {{1, 1, 1, -1}, {1, 1, -1, -1}, {-1, -1, 1, -1}, {-1, 1, -1, 1}};

But I think, in the spirit of Mathematica programming and functional programming, is that one should not do these things. i.e. functions should not have side-effects. To modify something, write newValue = foo[ oldValue ] and pass things by value, which is the default.

flip[1, 1, Unevaluated[s]];
s
(*  {{-1, 1, 1, -1}, {1, 1, -1, -1}, {-1, -1, 1, -1}, {-1, 1, -1, 1}}  *)
ClearAll[flip];
flip[posX_, posY_, lattice_] := 
  Module[{x = posX, y = posY}, 
   lattice = 
    ReplacePart[lattice, {y, x} -> -valueAtPos[x, y, lattice]] //. {{1} :> 
       1, {-1} :> -1}
   ];
Attributes[flip] = HoldAll;
valueAtPos[positionX_, positionY_, lattice_List] := 
 Flatten[Take[lattice, {positionY, positionY}, {positionX, positionX}]]
s = {{1, 1, 1, -1}, {1, 1, -1, -1}, {-1, -1, 1, -1}, {-1, 1, -1, 1}};

But I think, in the spirit of Mathematica programming and functional programming, is that one should not do these things. i.e. functions should not have side-effects. To modify something, write newValue = foo[ oldValue ] and pass things by value, which is the default.

see also passing-large-list-by-reference and does-pass-by-value-affect-the-performance-of-function-calls

Source Link
Nasser
  • 150.4k
  • 12
  • 161
  • 374
Loading