6

Bug introduced in 10.4 and persisting through 11.1.1


Up until 10.4 you could not match on internal Association structure at all: https://mathematica.stackexchange.com/a/119542/6804

Now you can, but it seems flawed still: the following patterns should match <|"c" -> {0}|> but not <|"c" -> {1}|>. These work:

gok1[KeyValuePattern@{"c" -> c_List /; First@c == 0}] := 0;
gok2[KeyValuePattern@{"c" -> c_List}] := 0 /; First@c == 0;

(I still don't understand why they support the second variant, after all the RHS in := should not be a Pattern...).

But this one does not:

gfail[KeyValuePattern@{"c" -> c_List}] /; First@c == 0 := 0;

giving First::normal: Nonatomic expression expected at position 1 in First[c]. but only the first time it is used, e.g. via

gfail[<|"c" -> {0}|>]
gfail[<|"c" -> {1}|>]

or

gfail[{"c" -> {0}}]
gfail[{"c" -> {1}}]

So the culprit seems to be the KeyValuePattern. If it is not involved, everything works fine:

hok[{"c" -> c_List}] /; First@c == 0 := 0;
hok1[{"c" -> c_List /; First@c == 0}] := 0;
hok2[{"c" -> c_List}] := 0 /; First@c == 0;

hok[{"c" -> {0}}]
hok[{"c" -> {1}}]
hok1[{"c" -> {0}}]
hok1[{"c" -> {1}}]
hok2[{"c" -> {0}}]
hok2[{"c" -> {1}}]

Am I missing something or can somebody confirm this as a probable bug?

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
masterxilo
  • 5,739
  • 17
  • 39
  • 1
    It seems in patt /; test c isn't shared but for lhs:>rhs/;test it is: a : KeyValuePattern[{"c" -> c_List}] :> a /; (First[c] === 0). Just an observation, don't know if the observerd behavior is to be expected (isn't for me). – Kuba Jun 28 '16 at 20:55
  • Is it useful to make contact with these answers? (108925) (109383) – Jess Riedel Jun 29 '16 at 01:04

2 Answers2

4

It is a bug that the local variable c isn't shared with Condition when the latter appears at the LHS outside of the KeyValuePattern. The following simplified examples demonstrate the bug:

gfail1[KeyValuePattern@{"c" -> c_}] /; c == 0 := 0
gfail2[KeyValuePattern@{"c" -> c_} /; c == 0] := 0

gfail1[<|"c" -> 0|>]
gfail2[<|"c" -> 0|>]
gfail1[<|"c" -> 0|>]

gfail2[<|"c" -> 0|>]

These cases demonstrate the expected behavior:

gok1[KeyValuePattern@{"c" -> c_ /; c == 0}] := 0
gok2[KeyValuePattern@{"c" -> c_}] := 0 /; c == 0

gok1[<|"c" -> 0|>]
gok2[<|"c" -> 0|>]
0

0

Please report it to the tech support.


(I still don't understand why they support the second variant, after all the RHS in := should not be a Pattern...).

Actually the RHS with Condition IS a part of the pattern expression, please read this excellent answer by Leonid Shifrin.

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
2

Consider

test[p : KeyValuePattern@{"c" -> c_List}] /; First[p["c"]] == 0 := $Succeeded
test[p : KeyValuePattern@{"c" -> c_List}] := $Failed

then

test[<|"c" -> {0, 1}|>]

$Succeeded

test[<|"c" -> {1, 1}|>]

$Failed

Perhaps that is form you are looking for.

m_goldberg
  • 107,779
  • 16
  • 103
  • 257