Querying nested Rule expressions of the form

a -> v -> b // FullForm


for Keys, Values seems inconsistent in List and Association and causes Query to fail depending on the level where these are applied:

data = {a -> v -> b, b -> v -> c} 

Getting Keys, Values from List is consistent with the full form of each part:

data // Map[Keys]

{a, b}

data // Map[Values]

{v -> b, v -> c}

Converting to Association correctly gives:

data // Association // Map[Keys]

<|a -> v, b -> v|>

data // Association // Map[Values]

<|a -> b, b -> c|>

But Query fails in emulating Map

data // Query[All, Keys]     (*  // Normal *)

{Missing["PartInvalid", Keys], Missing["PartInvalid", Keys]}

(Similarly for Values).

Also fails when wrapping either the List or Association in Dataset

Dataset[Association[data]][All, Keys] // Normal

<|a -> Missing["PartInvalid", Keys], b -> Missing["PartInvalid", Keys]|>

Tech support ticket filed. Is there a workaround?

Motivation: exploring triple-stores: data structures used in graph databases like Neo and Tiger that store relations of the form subject-verb-object, or "alice"-> follows -> "bob".

  • 1
    $\begingroup$ I don't see any inconsistency with the Maps, remember Mapping over Associations only effects values $\endgroup$ – M.R. May 29 '19 at 16:04
  • $\begingroup$ @M.R, that's right, Map should act on values, but in this case the values are themselves Rules, specifically v->b, v->c, which have valid Keys (v for both) and valid Values ie, (b and c) $\endgroup$ – alancalvitti May 29 '19 at 16:10
  • 1
    $\begingroup$ Right, so they work as expected, Keys /@ <|a -> v -> b, b -> u -> c|> yeilds <|a -> v, b -> u|> and Keys /@ {a -> v -> b, b -> u -> c} yields {a, b}. Is that not expected? $\endgroup$ – M.R. May 29 '19 at 16:31
  • $\begingroup$ @M.R., you're right, so Map works but not Query. Will edit. $\endgroup$ – alancalvitti May 29 '19 at 16:34

I think your issue can be boiled down to the following inconsistency:

data //Query[All, Keys]
data //Query[All, g]
% /. g->Keys

{Missing["PartInvalid", Keys], Missing["PartInvalid", Keys]}

{g[a -> v -> b], g[b -> v -> c]}

{a, b}

This suggests that you could try using the following as a workaround:

g[x__] := Keys[x]
data //Query[All, g]

{a, b}

  • 2
    $\begingroup$ +1. In version 12, the ultimate problem is in an internal function, exemplified by GeneralUtilities`Slice`PackagePrivate`part[a -> b, Keys]. The definition of that function does not allow for the fact that Keys (and Values) can operate upon expressions with the head Rule. $\endgroup$ – WReach May 29 '19 at 18:38
  • $\begingroup$ @WReach, What the hell is Slice? It's not in the language. Is it one of those type hacks like Dataset is full of? (ie C++ template looking Vect and Struct) that have nothing to do with WL expressions and pattern matching? You know there are bugs in Dataset that still haven't been fixed since 2014. $\endgroup$ – alancalvitti May 30 '19 at 14:49
  • $\begingroup$ @alancalvitti Concidentally, in a recent livestream SW was similarly unimpressed when he saw GeneralUtilities appear in the Normal form of a Query. In the discussion that followed, it was suggested that any such utility functions ought to be promoted to first-class documented functions. $\endgroup$ – WReach May 30 '19 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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