Duplicate the swap function
Attributes[swap] = HoldAll;
swap[x_, y_] := {x, y} = {y, x};
x = 1;
y = 2;
swap[x, y];
{x, y}
{2, 1}
There are two characteristics of this code worth noting. The first is the HoldAll
Attribute:
- How do I treat elements in a list as variables inside a module?
- When should I, and when should I not, set the HoldAll attribute on a function I define?
- Pass function or formula as function parameter
- How to modify function argument?
The second is the evaluation of {x, y} = {y, x}
itself, which is related. Let us consider how else we might implement this. Essentially we need to store the present values of x
and y
before reassigning these Symbols to the opposite value. That might be done verbosely like this:
x1 = x;
y1 = y;
x = y1;
y = x1;
This requires that two additional Symbols be introduced which is less clean than ideal. Instead we can store the original values within the evaluation sequence itself. First understand that Set
(short form =
) has the HoldFirst
attribute. This means that in the expression {x, y} = {y, x}
(long form Set[{x, y}, {y, x}]
) the second argument will be evaluated before Set
does anything, but the first argument will be held in an unevaluated form. Indeed we find this in the output of TracePrint
:
x = 1; y = 2;
TracePrint[{x, y} = {y, x}];
(* other print lines omitted*)
{x, y} = {2, 1}
Thanks to the fact that Set
operates on lists this then performs the reassignment that we want. If it did not we could still perform this action without using intermediate (temporary) variables like x1
and y1
by using the same kind of evaluation control.
(x = #2; y = #1) &[x, y]
Here a Function
is used which (by default) evaluates its arguments but holds the body of the function (x = #2; y = #1)
unevaluated until its Slot
s are filled.
Just a reminder for advanced users, to show the complexity of the problem :
keywords : David Wagner power programming swap byname