Wolfram Research

Function Repository Resource:

UnevaluatedAssociation

Source Notebook

Construct an association without evaluating any of the keys or values

Contributed by: Richard Hennigan (Wolfram Research)

ResourceFunction["UnevaluatedAssociation"][key1val1,key2val2,]

creates an Association from the given keys and values without evaluating any of the keyi or vali.

ResourceFunction["UnevaluatedAssociation"][,Evaluate[keyi]vali,]

evaluates keyi before constructing the association.

ResourceFunction["UnevaluatedAssociation"][,keyiEvaluate[vali],]

evaluates vali before constructing the association.

Details and Options

ResourceFunction["UnevaluatedAssociation"][{key1val1,}] gives <|key1val1,|>.
In ResourceFunction["UnevaluatedAssociation"][,keyResourceFunction["UnevaluatedAssociation"][],], the inner ResourceFunction["UnevaluatedAssociation"][] will automatically be initialized.
In ResourceFunction["UnevaluatedAssociation"][,keyResourceFunction["UnevaluatedAssociation"][],], the inner ResourceFunction["UnevaluatedAssociation"][] will remain uninitialized.
Keys and values can be selectively evaluated prior to constructing the association by wrapping them in Evaluate.
The value associated with a given key can be extracted using assoc[key]. If the key would evaluate, use assoc[Unevaluated[key]] instead.
To get the vali associated with keyi in assoc without evaluating either of them, use Extract[assoc,Unevaluated[{Key[keyi]}],h], where h is some head that holds its arguments.
To get Values[assoc] without evaluation, use Values[Map[h,assoc]].
To get Keys[assoc] without evaluation, use Keys[KeyMap[h,assoc]].
ResourceFunction["UnevaluatedAssociation"] has the option "AlwaysReturnAssociation", which defaults to False. In cases where ResourceFunction["UnevaluatedAssociation"][] does not construct a valid association assoc such that AssociationQ[assoc] is True, the result will not have the head Association. Setting "AlwaysReturnAssociation" to True will ensure that the output always has the head Association, even if it is not AssociationQ.
Options for ResourceFunction["UnevaluatedAssociation"] must be set using SetOptions, since specifying options as arguments would be interpreted as rules for the association.

Examples

Basic Examples

An Association in which keys and values are stored without evaluation:

In[1]:=
ResourceFunction["UnevaluatedAssociation"][1 + 1 -> Echo[2], 2 + 2 -> Echo[4]]
Out[1]=

Extract the value associated with key 1+1:

In[2]:=
%[Unevaluated[1 + 1]]
Out[2]=

Convert a list of rules to an association:

In[3]:=
ResourceFunction[
 "UnevaluatedAssociation"][{1 + 1 -> Echo[2], 2 + 2 -> Echo[4]}]
Out[3]=

Create an unevaluated association from an uninitialized association:

In[4]:=
ResourceFunction[
 "UnevaluatedAssociation"][<|Now -> DateObject[], Red -> RGBColor[1, 0, 0]|>]
Out[4]=

Specify that a key should be evaluated:

In[5]:=
ResourceFunction["UnevaluatedAssociation"][
 Evaluate[Echo[a]] -> Echo[1], Echo[b] -> Echo[2]]
Out[5]=

Specify that a value should be evaluated:

In[6]:=
ResourceFunction["UnevaluatedAssociation"][
 Echo[a] -> Evaluate[Echo[1]], Echo[b] -> Echo[2]]
Out[6]=

Many operations can be done while preserving the original expressions:

In[7]:=
assoc = ResourceFunction["UnevaluatedAssociation"][1 + 1 -> 2*1, 2 + 2 -> 2*2]
Out[7]=
In[8]:=
Map[Hold, assoc]
Out[8]=
In[9]:=
Select[assoc, # > 3 &]
Out[9]=
In[10]:=
Reverse[assoc]
Out[10]=
In[11]:=
Join[assoc, <|a -> b|>]
Out[11]=

Append an element without evaluation:

In[12]:=
Append[ResourceFunction["UnevaluatedAssociation"][1 + 1 -> Echo[2], 2 + 2 -> Echo[4]], Unevaluated[3 + 3 -> Echo[6]]]
Out[12]=

Scope

UnevaluatedAssociation can be used to join associations with new associations/values:

In[13]:=
assoc = ResourceFunction["UnevaluatedAssociation"][Echo[a] -> Echo[1],
   Echo[b] -> Echo[2]]
Out[13]=
In[14]:=
ResourceFunction["UnevaluatedAssociation"][assoc, Echo[c] -> Echo[3]]
Out[14]=
In[15]:=
ResourceFunction[
 "UnevaluatedAssociation"][assoc, <|Echo[c] -> Echo[3], Echo[d] -> Echo[4]|>]
Out[15]=

Use the three-argument form of Extract to get values without evaluating them:

In[16]:=
assoc = ResourceFunction["UnevaluatedAssociation"][1 + 1 -> Echo[2], 2 + 2 -> Echo[4]]
Out[16]=
In[17]:=
assoc[Unevaluated[1 + 1]]
Out[17]=
In[18]:=
Extract[assoc, Unevaluated[{Key[1 + 1]}], Hold]
Out[18]=

Nested associations are not initialized:

In[19]:=
ResourceFunction["UnevaluatedAssociation"][1 + 1 -> Echo[2], 2 + 2 -> <|2*2 -> Echo[4]|>]
Out[19]=

Use Evaluate to force them to initialize:

In[20]:=
ResourceFunction["UnevaluatedAssociation"][1 + 1 -> Echo[2], 2 + 2 -> Evaluate[<|2*2 -> Echo[4]|>]]
Out[20]=

Nested uses of UnevaluatedAssociation for values are automatically initialized:

In[21]:=
ResourceFunction["UnevaluatedAssociation"][1 + 1 -> Echo[2], 2 + 2 -> ResourceFunction["UnevaluatedAssociation"][2*2 -> Echo[4]]]
Out[21]=

Using RuleDelayed will prevent this initialization:

In[22]:=
ResourceFunction["UnevaluatedAssociation"][1 + 1 -> Echo[2], 2 + 2 :> ResourceFunction["UnevaluatedAssociation"][2*2 -> Echo[4]]]
Out[22]=

Get Values without evaluating them by using Map and Hold:

In[23]:=
assoc = ResourceFunction["UnevaluatedAssociation"][Echo[a] -> Echo[1],
   Echo[b] -> Echo[2]]
Out[23]=
In[24]:=
Values[Map[Hold, assoc]]
Out[24]=

Get Keys without evaluating them by using KeyMap and Hold:

In[25]:=
assoc = ResourceFunction["UnevaluatedAssociation"][Echo[a] -> Echo[1],
   Echo[b] -> Echo[2]]
Out[25]=
In[26]:=
Keys[KeyMap[Hold, assoc]]
Out[26]=

Options

AlwaysReturnAssociation

By default, in cases where a valid association cannot be constructed, UnevaluatedAssociation does not return an Association:

In[27]:=
ResourceFunction["UnevaluatedAssociation"][a, Echo[b] -> Echo[2]]
Out[27]=
In[28]:=
Head[%]
Out[28]=

Specify that UnevaluatedAssociation should always return an Association, even if it is not AssociationQ:

In[29]:=
SetOptions[ResourceFunction["UnevaluatedAssociation"], "AlwaysReturnAssociation" -> True]
Out[29]=
In[30]:=
ResourceFunction["UnevaluatedAssociation"][a, Echo[b] -> Echo[2]]
Out[30]=
In[31]:=
Head[%]
Out[31]=

Restore the default behavior:

In[32]:=
SetOptions[ResourceFunction["UnevaluatedAssociation"], "AlwaysReturnAssociation" -> False]
Out[32]=

Properties and Relations

UnevaluatedAssociation creates an Association object:

In[33]:=
assoc = ResourceFunction[
  "UnevaluatedAssociation"][<|1 + 1 -> Echo[2], 2 + 2 -> Echo[4]|>]
Out[33]=
In[34]:=
Head[assoc]
Out[34]=
In[35]:=
AssociationQ[assoc]
Out[35]=

Values extracts and evaluates values:

In[36]:=
Values[ResourceFunction[
  "UnevaluatedAssociation"][<|Echo[a] -> Echo[1], Echo[b] -> Echo[2]|>]]
Out[36]=

Keys extracts and evaluates keys:

In[37]:=
Keys[ResourceFunction[
  "UnevaluatedAssociation"][<|Echo[a] -> Echo[1], Echo[b] -> Echo[2]|>]]
Out[37]=

Normal turns an association into a list of rules, which will evaluate keys and values:

In[38]:=
Normal[ResourceFunction[
  "UnevaluatedAssociation"][<|Echo[a] -> Echo[1], Echo[b] -> Echo[2]|>]]
Out[38]=

The values associated with keys can be changed:

In[39]:=
assoc = ResourceFunction[
  "UnevaluatedAssociation"][<|Echo[a] -> Echo[1], Echo[b] -> Echo[2]|>]
Out[39]=
In[40]:=
assoc[Unevaluated[Echo[a]]] := Echo[3]

This will change the Rule to a RuleDelayed, however:

In[41]:=
assoc
Out[41]=

An empty UnevaluatedAssociation is the same as an empty Association:

In[42]:=
ResourceFunction["UnevaluatedAssociation"][] === <||>
Out[42]=

Possible Issues

Replacing the head of an Association loses keys:

In[43]:=
assoc = ResourceFunction["UnevaluatedAssociation"][Echo[a] -> Echo[1],
   Echo[b] -> Echo[2]]
Out[43]=
In[44]:=
ReplacePart[assoc, {0} -> Hold]
Out[44]=

Some operations will evaluate both the keys and values:

In[45]:=
assoc = ResourceFunction["UnevaluatedAssociation"][Echo[b] -> Echo[2],
   Echo[a] -> Echo[1]]
Out[45]=
In[46]:=
Sort[assoc]
Out[46]=

Options cannot be passed to UnevaluatedAssociation as arguments, since they will be interpreted as key-value pairs:

In[47]:=
ResourceFunction["UnevaluatedAssociation"][a -> 1, "AlwaysReturnAssociation" -> True]
Out[47]=
In[48]:=
ResourceFunction["UnevaluatedAssociation"][x, y, z, "AlwaysReturnAssociation" -> True]
Out[48]=

Use SetOptions instead:

In[49]:=
SetOptions[ResourceFunction["UnevaluatedAssociation"], "AlwaysReturnAssociation" -> True]
Out[49]=
In[50]:=
ResourceFunction["UnevaluatedAssociation"][x, y, z]
Out[50]=
In[51]:=
SetOptions[ResourceFunction["UnevaluatedAssociation"], "AlwaysReturnAssociation" -> False]
Out[51]=

Resource History

See Also

License Information