59

Preamble This is a very good question, because answering it will make it very clear what immutability means, both in general and in the context of Associations. General A few general words on immutability Associations are immutable data structures. This means that they carry no state, and a copy of an Association is another completely independent Association....


32

I believe Increment (more accurately PreIncrement as george2079 noted) is essentially this: SetAttributes[inc, HoldFirst] inc[a_] := a = (a + 1) This exhibits the same behavior, e.g. f[] := (Print[#]; #) &@RandomInteger[{1, 3}] v = {0, 0, 0}; inc @ v[[f[]]]; 2 1 Here f[] is evaluated twice because parameter a is used twice within Set. On the ...


31

I hesitate to add anything after @Leonid's comprehensive answer, but I'd like to point out that an easy way to achieve the stated goal is to define f like this: f[x_] := <| x, "isFirstValueTrue" -> x@"firstValue" |> ... which yields the desired result when mapped across the associations in x: f /@ x (* { <|"firstValue" -> True, "...


22

You asked for a general explanation instead of just focusing on specific application examples, so here it goes ... The concepts of "pass by reference" and "pass by value" that you may know from languages like C do not apply very well to Mathematica. Do not try to think in this framework. The right question is not "how to pass by ...


21

Update: Version 10 built-in function Values does value extraction conveniently for rules appearing in lists of arbitrary lengths and depths: {{x1, y1}, {x2, y2}} = Values[Solve[y^2 == 13 x + 17 && y == 193 x + 29, {x, y}]] (* {{(-11181-Sqrt[2242057])/74498,1/386 (13-Sqrt[2242057])}, {(-11181+Sqrt[2242057])/74498,1/386 (13+Sqrt[2242057])}} *) ...


18

General considerations To my mind, the only robust way to do this is to build some custom object model in Mathematica, and in particular to restrict the way values can be changed to some well-defined route you can control. Because, as it follows from one of the discussions you linked to, there seems to be no reliable way to intercept arbitrary value changes ...


16

The problem here is that in Mathematica, parameters of a function are not local variables. So trying to modify a parameter of a function inside it's body will lead to an error. The reason is that function arguments are evaluated, when the function is called so that it is actually the result of this evaluation that's textually substituted for the function ...


15

{x1, x2} = x /. Solve[x^2 + 3 x + 2 == 0, x] {-2, -1}


15

The reason is that AppendTo and PrependTo actually replace the whole list with a new one, rather than only changing a single element. In that sense, they are not really "in-place". They are in-place in the sense that the result gets assigned back to the same variable. You can see using Trace, that AppendTo and PrependTo in fact expand: bar[1]={4,3,2,1}; ...


15

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 ...


14

This is an old discussion but is about an issue that resurfaces every now and then. One of the best (for a given sense of elegance) answers is the one posted on Stack Overflow ClearAll[f] SetAttributes[f, HoldAllComplete] f[a_, b_, c_] := { ToString@Unevaluated@a, ToString@Unevaluated@b, ToString@Unevaluated@c } f[a__] := Function[x, f[a, x], ...


14

I think the best way to understand this behavior is with this example, In[99]:= x = {a, b, c, d, e}; In[101]:= Length@x Out[101]= 5 In[102]:= x[[3]] = Nothing; In[103]:= Length[x] Out[103]= 4 In[104]:= Block[{Nothing}, Length[x]] Out[104]= 5 When you say x[[3]] = Nothing, you are not deleting an element from x. x is still a 5-element list. But x is ...


13

Utilizing ValueFunction as mentioned here, we could do something like this: SetAttributes[Observe, HoldFirst]; Observe[s_Symbol, fn_] := With[{VF := Experimental`ValueFunction[s]}, VF = If[ValueQ @ VF, ReplacePart[VF, {2, 2, 2} -> Append[VF[[2, 2, 2]], fn]], Function[Null, Table[f[##], {f, {fn}}], HoldAll] ]; ] We will need to include ...


13

The way Set works in setting parts of an expression is this: symb[[..<part specification>..]] = values; The component symb must be a symbol (i.e. with head Symbol). In the OP's code, p[[All,3]][[1;;2]] = {1,1}; The symb component is p[[All,3]], which is not a symbol. Fix as @kglr suggests, p[[1 ;; 2, 3]] = {1, 1}; As for evaluating p[[All,3]][[...


12

This question is done and dusted but it is such a good one (together with the existing answers) for demonstrating and encapsulating the different ways Associations can be modified, that I'd like to belatedly summarise while suggesting some other takeaways. In particular, how it can further highlight a mutable and immutable dichotomy or perhaps more ...


11

I propose these: SetAttributes[def, HoldAllComplete] def[s_Symbol, v_] := SetDelayed @@ Hold[s[x_], v] def[s_Symbol, v_] := With[{L := s[x_]}, L := v] def[s_Symbol, v_] := Reverse @ Unevaluated[v := s[x_]] The HoldAllComplete (or SequenceHold) attribute is necessary for an assignment such as: def[q, Sequence[1, 2, x]] head[q[5]] head[1, 2, 5] Also ...


11

Updated 14-10-2014 see solution at the end. Updated 17-07-2015 Bug no longer present in version 10.2 This answer is basically for documentation of the problem. The credit goes mainly to the people participating in the comments. Diagnostics I can reproduce you observation on two different computers both, Windows 7 Pro 64, SP 1 running Mathematica 10.0.1. ...


11

Now that OP has accepted an answer, implicitly making the results from it correct, here's a much faster method than the fastest there (as in 3x to nearly order of magnitude faster, depending on amount of missing points): v2 = c2 = ConstantArray[0, Length@v1]; v2[[o1]] = o2; c2[[o1]] = o1; c2[[Range[1, First@o1]]] = Range[1, First@o1]; v2 = v2[[With[{xx = c2}...


11

No, not a bug. Let's think about how AppendTo may be implemented (even though the actual implementation isn't inspectable). SetAttributes[appendTo, HoldFirst] appendTo[a_, val_] := (a = Append[a, val]) What happens if we evaluate the following? appendTo[ a[[ RandomInteger[{1,3}] ]], x ] It simply does this: a[[ RandomInteger[{1,3}] ]] = Append[a[[ ...


11

The problem is not related to Set in general but to how Set works with Part on a left hand side. Following Set::setps message documentation This message is generated when a part assignment is used for the value of an expression other than a symbol. Part assignments are implemented only for parts of the value of a symbol. Shortly Part[(*something*), (*spec*)...


11

He is simply saying that the first argument of Set is not evaluated before Set creates the definition. However, the sub-parts of the first argument are all evaluated, including the head(i.e. part 0). Thus in f[x] = y f[x] is not evaluated in the sense that any previous definition similar to f[z_] := z^2 will be ignored. However, f is evaluated and x is ...


10

You need to use InputForm to see the actual value of the numbers. x = -15*0.1 + 6*0.1; InputForm[x] Now when you wrote a[-15*0.1 + 6*0.1] = 5 Now 5 is actually stored in a[-0.8999999999999999] and not in a[-0.9], this is why a[-0.9] does not return the value 5 you expected. But when you wrote a[-0.8999999999999999] it did. Now, as to why -15*0.1 + ...


10

Reanalysis My earlier assertions were incorrect or at least incomplete. I now believe the problem in your code originates because of a particular behavior that can be seen in this separate example: asc = <|foo -> <|bar -> <|baz -> 1|>|>|> <|foo -> <|bar -> <|baz -> 1|>|>|> asc[foo][bar][baz] = 2; asc ...


10

I will interpret the question "Why?" to be asking What useful purpose does it serve that SetDelayed evaluates its first argument? In the standard evaluation sequence, the evaluation of f[x] begins with evaluating the head f. Thus if f = g, then f[x] first evaluates to g[x]; then any definitions of g would be applied. If SetDelayed did not evaluate f[x_],...


10

Here's the issue. In the second (non-working) code, RandomInteger[{1, Length[a]}] is evaluated twice, as we can see by Traceing the evaluation: SeedRandom[2] a = {{1}, {2}, {3}}; Trace[AppendTo[a[[RandomInteger[{1, Length[a]}]]], RandomInteger[9]], TraceInternal -> True] {RandomInteger[9], 8} AppendTo[a[[RandomInteger[{1, Length[a]}]]], 8] {{a, {{1}, {...


10

Kuba's answer explains why the first form does not work, but it does not address why the second form does work. That has been discussed in other questions DownValue assignment using Apply Why is the first argument of the SetDelayed evaluated? https://stackoverflow.com/q/5846756/618728 https://stackoverflow.com/q/7408310/618728 One can see that the head of ...


10

This is due to the special behavior of SetDelayed (:=) with regards to the first argument (see e.g. this question): The arguments of the l.h.s. are evaluated by SetDelayed, which causes the error you are seeing - after all, SeriesData[_, _, coeff_, _, _, _] is not a valid SeriesData construct. This is what HoldPattern is designed for: It prevents evaluation ...


9

Here's a way: var1 = 10; var2 = 11; var3 = 17; var4 = 5; compvar := {var1, var2, var3, var4} compvar; (*all variables assigned*) ClearAll[f]; SetAttributes[f, {HoldAll}]; f[x_, y__] := Flatten@{f[x], f[y]} f[x_] := SymbolName@Unevaluated@x OwnValues[compvar] /. {HoldPattern[y_] :> {x__}} :> f[x] (* {"var1", "var2", "var3", "var4"} *)


9

If I've understood the question correctly, you need to put the Unset inside the function definition, e.g. mem : f[m_] := ( mem = f[m - 1] + f[m - 2]; If[m > 3, Unset@f[m - 2]]; mem) f[0] = 0; f[1] = 1; Now you can compute, say, f[50] and get the speed advantage of memoization, but only ever keeping the two values required for the next iteration. ...


9

In general I would say that the Observer pattern is not applicable to Mathematica code, since in my experience most Mathematica code is not event driven and the Observer pattern makes no sense without events. But a GUI application taking a state-machine approach and using Refresh with the option TrackedSymbols, however, can certainly implement the Observer ...


Only top voted, non community-wiki answers of a minimum length are eligible