12
$\begingroup$

I'm trying to wrap my head around how to work with Mathematica for building (computable) domain specific knowledge. One particular thing I didn't quite understand is how to create symbols for operations which are to be applied (computed) only for specific entity-types. I understand how I can restrict the pattern-matching to basic datatypes (i.e using x_Integer as parameter to restrict input to only integers for example). But all entities share the exact same head (Entity), so how do I make the pattern understand which specific entity-type I want to match on?

ex:

f[x_{Planet entity}]:=y

which I'd like to evaluate to y if, for example, x="Entity["Planet", "Mercury"]", but not if Entity["Country", "Sweden"]

$\endgroup$
2
  • $\begingroup$ I'm not sure if there is a specific function that'll check for entity-types, but maybe you can just use PatternTest or Condition to check if it's the 'correct' type of entity. Something like f[x_?MemberQ[EntityList["Planet"],#]&]? $\endgroup$
    – void life
    Jan 13, 2019 at 13:47
  • 3
    $\begingroup$ x : HoldPattern[Entity["Planet", __]]? $\endgroup$
    – Kuba
    Jan 13, 2019 at 14:02

2 Answers 2

12
$\begingroup$

As pointed out by Kuba in comments, when we make a function definition the pattern variables are not restricted to be simple x_head. So you can create a definition like

f[ent:HoldPattern[Entity["Planet", planetName_]]] := <do something>

The HoldPattern is only needed if you want to make the definition but avoid evaluation or package autoloading. Since Entity[ "Planet", planetName_] doesn't actually evaluate, here it is used to avoid autoloading the entity framework when making the definition.

The above definition would fire for even invalid planet entities - it would work with Entity["Planet", "Bob"] for example. You could go further with your definition, and restrict it to only valid entities, if only there were a ValidEntityQ function. Evaluating ?EntityFramework`* we see there is a function EntityFramework`EntityExistsQ that seems like what we want. It is an undocumented function, so it could stop working at some point in the future, but it seems to be present in every version of the entity framework I have available to me now and it isn't a Private` function so I would think it relatively safe to use.

So you could make your definition like

f[ent:HoldPattern[Entity["Planet", planetName_]]] /; 
      EntityFramework`EntityExistsQ[ent] := <do something>

f[ent___] := $Failed

to make it only fire for valid planet entities.

$\endgroup$
3
  • 1
    $\begingroup$ But there is a Planet Bob: cybernations.wikia.com/wiki/Planet_Bob :) $\endgroup$
    – Michael E2
    Jan 13, 2019 at 16:01
  • $\begingroup$ Nice, one follow-up question only; are there any performance considerations regarding this pattern? $\endgroup$
    – Whil
    Jan 13, 2019 at 18:31
  • 2
    $\begingroup$ @Whil These guards are usually fairly safe to use and the performance seems fine. I was about to write an answer in line of the one above but it is already perfect :) $\endgroup$ Jan 13, 2019 at 22:18
1
$\begingroup$

There is EntityTypeName (from 2014) so one could do :

g[x_] /; EntityTypeName[x] === "Planet" := x["Mass"]

Check :

g[Entity["Planet", "Mars"]]

(* Quantity[6.417*10^23, "Kilograms"] *)

g[Entity["Species", "Species:FelisCatus"]]

(* g[Entity["Species", "Species:FelisCatus"]] *)

g[42]

enter image description here

(* g[42] *)

$\endgroup$

Your Answer

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

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