1
$\begingroup$

I'm puzzled by a behaviour of EntityValue, where I find it being unevaluated. Here is a minimal example. Consider the following custom EntityStore:

store = EntityStore[{
   "Group" -> <|
     "Entities" -> <|
       "GroupA" -> <|
         "name" -> "Group A",
         "size" -> 2,
         "members" -> {
           Entity["Individual", "Claus"],
           Entity["Individual", "Andrea"]
           }
         |>,
       "GroupB" -> <|
         "name" -> "Group B",
         "size" -> 2,
         "members" -> {
           Entity["Individual", "John"],
           Entity["Individual", "Claudia"]
           }
         |>
       |>
     |>,
   "Individual" -> <|
     "Entities" -> <|
       "Claus" -> <|"name" -> "Claus Smith", "age" -> 25|>,
       "Andrea" -> <|"name" -> "Andrea Fisher", "age" -> 35|>,
       "John" -> <|"name" -> "John Allen", "age" -> 45|>,
       "Claudia" -> <|"name" -> "Claudia Wilson", "age" -> 60|>
       |>
     |>
   }
  ]

Let's register it:

EntityRegister[store]

and then query it:

assoc = EntityValue["Group", "PropertyAssociation"]

which gives as expected:

{<|
  EntityProperty["Group", "members"] -> {Entity["Individual", "Claus"], Entity["Individual", "Andrea"]}, 
  EntityProperty["Group", "name"] -> "Group A", 
  EntityProperty["Group", "size"] -> 2
|>, 
<|
  EntityProperty["Group", "members"] -> {Entity["Individual", "John"], Entity["Individual", "Claudia"]}, 
  EntityProperty["Group", "name"] -> "Group B", 
  EntityProperty["Group", "size"] -> 2
|>}

Now let's say we'd like to make this association hierarchical by replacing the Individual properties by their own property associations:

ds = assoc /. {Entity["Individual", n_] :> EntityValue[Entity["Individual", n], "PropertyAssociation"]}

This - unexpectedly to me - leaves the inner EntityValue expressions unevaluated:

{<|
  EntityProperty["Group", "members"] -> {EntityValue[Entity["Individual", "Claus"], "PropertyAssociation"], EntityValue[Entity["Individual", "Andrea"], "PropertyAssociation"]}, 
  EntityProperty["Group", "name"] -> "Group A", 
  EntityProperty["Group", "size"] -> 2|>,
 <|EntityProperty["Group", "members"] -> {EntityValue[Entity["Individual", "John"],  "PropertyAssociation"], EntityValue[Entity["Individual", "Claudia"], "PropertyAssociation"]}, 
  EntityProperty["Group", "name"] -> "Group B", 
  EntityProperty["Group", "size"] -> 2
|>
}

What's going on? Strangely, the inner EntityValue expressions evaluate when we somehow query them directly:

Lookup[ds, EntityProperty["Group", "members"]]

correctly yields

{{<|EntityProperty["Individual", "age"] -> 25, 
   EntityProperty["Individual", "name"] -> "Claus Smith"|>,
  <|EntityProperty["Individual", "age"] -> 35, 
   EntityProperty["Individual", "name"] -> "Andrea Fisher"|>},
 {<|EntityProperty["Individual", "age"] -> 45, 
   EntityProperty["Individual", "name"] -> "John Allen"|>,
  <|EntityProperty["Individual", "age"] -> 60, 
   EntityProperty["Individual", "name"] -> "Claudia Wilson"
|>}}

Why is this bugging me? I'd like to use this kind of replace mechanism to build up a hierarchical association expression from a hierarchical entity Store. Imagine a cascade of one-to-many relationships, like Continent -> Country -> Region -> City -> Neighbourhood" or something similar. I'd like to build up a hierarchy of associations by iteratively replacing the list of child-entities by their property associations.

So how can I control the evaluation of EntityValue?

Thanks.

$\endgroup$
1
  • $\begingroup$ Forgot to mention that I'm using Mathematica 12.0.0 $\endgroup$
    – Stephan
    Sep 28, 2020 at 18:53

1 Answer 1

2
$\begingroup$
ds = Replace[
  assoc, {Entity["Individual", n_] :> 
    EntityValue[Entity["Individual", n], "PropertyAssociation"]}, 
  Infinity]

or create a list of rules (using Normal) from the Association to use ReplaceAll.

ds = Normal[assoc] /. 
 Entity["Individual", n_] :> 
  EntityValue[Entity["Individual", n], "PropertyAssociation"]
$\endgroup$
2
  • $\begingroup$ Wow, Replace indeed works here. But I'm very puzzled by this! The replace action actually wasn't the issue here, as the replace itself worked. It was only the evaluation of the replacement-code that didn't take place. Why would Replace vs. ReplaceAll make a difference with respect to Evaluation of code after replacement? $\endgroup$
    – Stephan
    Sep 29, 2020 at 10:00
  • 1
    $\begingroup$ Because we are dealing with Associations. ReplaceAll will work as expected with a list of rules. Use Normal[assoc]. $\endgroup$ Sep 29, 2020 at 14:33

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.