3
$\begingroup$

The following code works

ccc = {};

AppendTo[ccc, 5];
ccc

and gives the output {5}

However, the following code does not work:

ccc={};
cc[emptySet_] := AppendTo[emptySet, 5]
cc[ccc]

Instead giving the error "AppendTo: {} is not a variable with a value, so its value cannot be changed."

Why does the second way not work?

  • From the error I'm guessing the definition of ccc is being substituted for for ccc, which is not a variable.
  • I imagine this is probably me just defining the function incorrectly, with some trivial error (maybe I need a hold or a condition something)
$\endgroup$
3
  • $\begingroup$ Look up the difference between passing by value vs passing by reference. In WL you are not passing the list itself, but rather just the values of the list. In this case you need to pass by reference $\endgroup$
    – enano9314
    Commented Mar 26, 2021 at 17:41
  • $\begingroup$ What you want is: cc[emptySet_] := Append[emptySet, 5]and not AppendTo. $\endgroup$ Commented Mar 26, 2021 at 17:49
  • 1
    $\begingroup$ Just do cc[Unevaluated@ccc] $\endgroup$
    – swish
    Commented Mar 26, 2021 at 17:56

2 Answers 2

6
$\begingroup$

To expand upon my comment, in order to pass by reference you can use Hold. So for instance:

In[1]:= foo[Hold[x_], val_] := AppendTo[x, val];

In[5]:= x = {};

In[6]:= foo[Hold@x, 2]

Out[6]= {2}

In[7]:= x

Out[7]= {2}

If you pass a held variable, this has the effect of passing by reference as opposed to by value, so we have access to the variable x rather than the data that x holds.

$\endgroup$
3
  • 8
    $\begingroup$ Or, you could add SetAttributes[cc, HoldFirst]; to the OP's code. $\endgroup$
    – Bob Hanlon
    Commented Mar 26, 2021 at 17:57
  • 1
    $\begingroup$ Thank you. I knew what what happening I just wasn't clear how to use Hold (or unevaluated or something else) to fix it. $\endgroup$
    – user106860
    Commented Mar 26, 2021 at 18:57
  • $\begingroup$ That's a good point. It is much more visually appealing in the code to not have to pass a bunch of variables as held. Though, I suppose one could argue that it is nice to explicitly Hold[var] the variables that need to be held to distinguish between what is reference vs value $\endgroup$
    – enano9314
    Commented Mar 26, 2021 at 20:30
5
$\begingroup$

According to AppendTo documentation:

AppendTo[x,elem] is equivalent to x=Append[x,elem].

When you use AppendTo[{}, 1] Mathematica can't evaluate {}=Append[{},1]. The solution is to give the variable's name to AppendTo and it'll figure it out. That's why Mathematica has something like Hold_sth.

The code below will raise error because when you write f[l1], Mathematica will replace variable's name with it's value and that makes the problem:

l1 = {};
f1[l_] := AppendTo[l, 1]
f1[l1]

(*Out: ERROR *)

Solution

You can do it in different ways, one natural way is to say to your function don't replace names with values:

l2 = {};
f2[l_] := AppendTo[l, 1]
SetAttributes[f2, HoldAll];
f2[l2]

(*Out: {1} *)
$\endgroup$
1
  • $\begingroup$ Thank you very much. I appreciate the answer. $\endgroup$
    – user106860
    Commented Mar 26, 2021 at 18:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.