6
$\begingroup$

First, Let use see

a = {"wx", "wy", "wz"};
AssociationThread[Flatten[StringCases[a, "w" ~~ d_ :> d]] -> a]

gives

<|"x" -> "wx", "y" -> "wy", "z" -> "wz"|>

Now comes the weird thing. Define

ClearAll[test];
test[] := Module[{a},
  a = {"wx", "wy", "wz"};
  AssociationThread[Flatten[StringCases[a, "w" ~~ d_ :> d]] -> a]
  ]

and run test[], gives

<|d -> "wz"|>

Why?

If you look at the test[]//Trace, you will find "w" ~~ d$_ :> d appears. What is d$_?

If we define

ClearAll[test];
test[] := Module[{},
  a = {"wx", "wy", "wz"};
  AssociationThread[Flatten[StringCases[a, "w" ~~ d_ :> d]] -> a]
  ]

or

ClearAll[test];
test[] := Module[{a,dList},
  a = {"wx", "wy", "wz"};
  dList = Flatten[StringCases[a, "w" ~~ d_ :> d]];
  AssociationThread[dList -> a]
  ]

then test[] gives correct answer.

Can someone explain the above behaviour? How could Module a variable affect the rule replacement of d?

$\endgroup$
2
  • 2
    $\begingroup$ If you simplify to Flatten[StringCases[a,"w"~~d_:>d]]->a inside the module you get {d,d,d}->{"wx","wy","wz"}. It looks like what's happening is something is broken when module isolates d. I don't know why it's isolating d, seems to be due to the ->a. Normally a$123 is used to create a unique version of scoped variables in things like Module. Because d_ becomes d$_ the rule is replacing with the actual symbol d and not the matched d$. The association is then merging the degenerate values for the key d. This looks like a bug to me, I'd report it. $\endgroup$
    – N.J.Evans
    Commented Nov 8, 2021 at 12:53
  • $\begingroup$ @N.J.Evans Thanks for reply. You're right. AssociationThread is irrelavent $\endgroup$
    – matheorem
    Commented Nov 8, 2021 at 13:02

1 Answer 1

8
$\begingroup$

This is a long-standing scoping issue. While we do not have a full resolution, often these can be addressed by a non-default system option setting.

SetSystemOptions["StrictLexicalScoping" -> True];

test[] := Module[{a},
  a = {"wx", "wy", "wz"};
  AssociationThread[Flatten[StringCases[a, "w" ~~ d_ :> d]] -> a]]

In[641]:= test[]

(* Out[641]= <|"x" -> "wx", "y" -> "wy", "z" -> "wz"|> *)
$\endgroup$
3
  • $\begingroup$ Thank you so much for answering. It indeed works. But I am wondering what bad side effects can we get if we always set SetSystemOptions["StrictLexicalScoping" -> True];. If for some reason we can not always set StrictLexicalScoping, what is the rule of thumb to avoid these unexpected behaviour(You know it is really a headache to track down such innocent "bug"s)? $\endgroup$
    – matheorem
    Commented Nov 8, 2021 at 15:14
  • 2
    $\begingroup$ I do not know offhand what issues will arise from that setting. We have had seen bad interaction between it and display of Dataset, seemingly from an incessant retriggering of formatting. Offhand I do not know if that remains problematic though. $\endgroup$ Commented Nov 8, 2021 at 23:40
  • $\begingroup$ Thank you for valuable information $\endgroup$
    – matheorem
    Commented Nov 9, 2021 at 0:45

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.