Message Boards Message Boards

1
|
4440 Views
|
5 Replies
|
6 Total Likes
View groups...
Share
Share this post:

Why can't I set a member of an Association?

I am sure that there is something I don't grasp about Associations. Here is my problem. I have an association. Call it A. It has a number of Keys, let's say 3 for the sake of argument and call them K1,K2 and K3. I also have 2 functions F1[] and F2[V,N] which takes an Association of type A as argument and a number N. In the call to F1[] I create that Association of type A in a variable V by calling a function initializeA[] which returns an Association of type A. I find that after I have created V, I can modify the values associated with keys K1,K2 and K3. Now, while in F1[] I call F2[V,N] and here lies the problem. Having passed V to F2 I find it impossible to set the values of V associated with the keys K1, K2 and K3. F2[V,N] returns V via Return[V]. The idea was to have F2 do some calculations and modify V. But I can't modify V while in F2. What I had to do was make my calculations in F2 and return the result and V with the following statement: { R,V} = F2[V,N]; while I am in F1[]. Only after having returned from F2[V,N] can I (while still in the call to F1[]) go ahead and modify some values in V, as in: AppendTo[V[[K1]],R]; I had hoped to place the line above inside F2[V,N].

This also leads to another question. Supposed I have created an initialized Association as above with V = initializeA[]. if I do, F2[V,#] & /@ {1,2,3,4,5} while hoping that F2[V,1] would modify V and that F2[V,2] would now have the modified value of V and then F2[V,3] would work with the value of V that was modified by the 2 previous calls to F. That did not work and I had to write a For[] loop so that I first call F2[V,1] and then modify V. Once that is done, in my next iteration of the loop I call F2[V,2] where V is the modified version (due to the call F2[V,1]). This 2nd call to F2 modifies V further and on the next iteration I call F2[V,3] and so on. That works. But I am nagged with the idea that I am missing something and that there is a ready made way to do this in Mathematica.

Any answers/suggestions?

POSTED BY: Henrick Jeanty
5 Replies

Thank you Arnoud. Your answer is very informative. Since (awkwardly) posting my question, I had looked more at the documentation regarding Associations and had come up with a better understanding of how association assignment worked. Your explanation cemented for me the understanding I had gleaned from reading the documentation. I also commend you on being able to answer an admittedly poorly asked question,

POSTED BY: Henrick Jeanty

Hi Henrick,

I am going to take a stab at this, but your question is written in a very complicated way (try to ask a smaller simpler question, if at all possible; that way people may be able to help you quicker).

Let's start with an association (note that you can type four spaces at the beginning of a line to make it look like code):

x = <| "a" -> 1, "b" -> 2, "c" -> 3 |>

And a function which gets called with an association:

f[y_Association] := y

Now I can call f with x:

f[x]

And this returns the association:

<| "a" -> 1, "b" -> 2, "c" -> 3 |>

OK, so far, so good. Not let's say you want to return an association but with a modified key or value. First, let's do it the wrong way:

f[y_Association] := ( y["a"] = 5; y)

If you do this and call it with:

f[x]

you get an error:

(Association::setps) <|a->3,b->2,c->3|> in the part assignment is not a symbol.

The reason for that is that y is not a variable but the expression that you passed in. So this:

f[x]

becomes:

f[<| "a" -> 1, "b" -> 2, "c" -> 3 |>]

and the code on the right hand side becomes:

( <| "a" -> 1, "b" -> 2, "c" -> 3 |>["a"] = 5; <| "a" -> 1, "b" -> 2, "c" -> 3 |>)

which leads to the error because you can not assign to an association.

To fix this you need to use a Module with a temporary variable to which you assign your association:

f[y_Association] := Module[ {z=y}, z["a"]=5; z ]

Now if you call it with x:

f[x]

you get no error and a plausible useful result:

<|"a" -> 5, "b" -> 2, "c" -> 3|>

If you want to add a key, you can do something like this:

f[y_Association] := Module[{z = y}, z["d"] = 5; z]

If you want to drop a key you can use either:

f[y_Association] := KeyDrop[y, "a"]

or:

f[y_Association] := Module[{z = y}, KeyDrop[z, "a"]]

(Module is not needed here, since you're not trying to assign to an expression in this case).

Finally, if you want your original x to be modified by f you simply assign to it:

x = f[x]

So here, f is called with x, uses a temporary variable to modify the expression, returns the result, and assigns that result to x.

I think the last bit might solve the second part of your question.

Hope this helps.

POSTED BY: Arnoud Buzing
Posted 3 years ago

Agree with the moderators, the text description is not at all clear. Please provide working code and examples. See this.

POSTED BY: Rohit Namjoshi

I agree. I will try, in the future, to be much more descriptive and to, when possible, provide code.

POSTED BY: Henrick Jeanty

Welcome to Wolfram Community!
Please read the rules: http://wolfr.am/READ-1ST

Please show your code beside explaining it in text. This will help other members to better understand your question.

POSTED BY: Moderation Team
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract