I was playing a little dirty, trying to get a template for defining a Curl[] operator.

I wrote the following rule, which I knew was going to spit out a few errors, because all symbols there (including the lists), were undefined:

Cross[{d[1], d[2], d[3]}, {2, 3, 4}] /. Times[a_, b_] -> b[[a]]

Notwithstanding the errors, the result I got was what I wanted:

(* {d[2][[4]] + d[3][[-3]], d[1][[-4]] + d[3][[2]], d[1][[3]] + d[2][[-2]]} *)

with a few more replacements, you can almost see the Curl[] operator materializing.

Sadly, I forgot that the symbol a was already in use in may main .nb, so I changed it to c. Look:

Cross[{d[1], d[2], d[3]}, {2, 3, 4}] /. Times[c_, b_] -> b[[c]]

But now the results are completely different!

(* {(-3)[[d[3]]] + 4[[d[2]]], (-4)[[d[1]]] + 2[[d[3]]], (-2)[[d[2]]] + 3[[d[1]]]} *)


I Traced the evaluation, and could easily find out where the both processes started to differ, but I couldn't understand why.

Any ideas?

  • 1
    $\begingroup$ You are using immediate rules, so there is a chance that b or c had prior values. Try with delayed rules instead, they scope their variables properly. $\endgroup$ Sep 6 '12 at 23:11
  • $\begingroup$ Hi @LeonidShifrin! I already tried that, and starting a fresh kernel ... nothing more came to my mind. $\endgroup$ Sep 6 '12 at 23:14
  • 2
    $\begingroup$ There can also be an issue with the ordering, since it is different for b,a and b,c, and Times is Orderless. Some unwanted reorderings may happen based on variable names. $\endgroup$ Sep 6 '12 at 23:16
  • $\begingroup$ Would it be possible to copy the original .nb and change the symbol a to something else to verify that original results return? Sometimes a small tweak somewhere else can have side-effects? If the original results do not come back, that would indicate that the symbol change from a to c is not the problem. $\endgroup$
    – Fred Kline
    Sep 6 '12 at 23:18
  • 1
    $\begingroup$ @LeonidShifrin Ohh If the evaluator reorders the pattern, that could be the issue $\endgroup$ Sep 6 '12 at 23:18

Just my little cent (yeah, cent is uncountable, there are too much of them around, so what)

Orderless (quite similarly to Flat) not only affects the automatic reordering of arguments. It also affects the pattern matching.

In here, both things are responsible for the behaviour. Not both together, but both by themselves. @R.M has already explained how the reordering of the patterns can ruin the party.

As to the second issue, when the pattern matcher is faced with matching an expression with an Orderless head, it knows it will have to check all combinations of orders of the patterns (until it finds one). So, for example

Hold[2 "a"] /. Hold[i_String j_Integer] :> {i, j}

{"a", 2}

A nice application of this behaviour is in @Mr.Wizard's answer

So, no matter the actual stored ordering of the patterns, it just gets ignored when matching

In conclusion, I support @R.M's advice on not to rely ever on the ordering of arguments of an Orderless head

  • 1
    $\begingroup$ Thanks for the answer and the links! $\endgroup$ Sep 7 '12 at 7:07

This is due to the Orderless attribute of Times. When you write Times[c_, b_], it automatically gets reordered to Times[b_, c_] even before any of the rules have been read. The reordering is in the sense of OrderedQ. Compare:

OrderedQ[{Pattern[b, Blank[]], Pattern[c, Blank[]]}]
(* True *)
OrderedQ[{Pattern[c, Blank[]], Pattern[b, Blank[]]}]
(* False *)

Once you realize that, you can begin to see why b[[c]] wouldn't give the right answer.

If you compare the two results closely, you'll see that each term is just flipped inside out (loosely speaking). i.e., d[2][[4]] becomes 4[[d[2]]], which is in accordance with b and c being flipped by the reordering. To further confirm this is the case, change the rule to Times[c_, b_] -> c[[b]] and you'll get the same answer as in the first case.

In general, it is probably not a good idea to use rely on the order of arguments in an orderless function for further processing/rules unless if the order doesn't matter in the latter case too (e.g. changing Times to Plus).

  • $\begingroup$ Ok OK blame me. For some reason I thought the Orderless attribute didn't play a role in patterns. Shame on me. Please someone comfort me saying that I am not completely stupid. $\endgroup$ Sep 6 '12 at 23:23
  • 1
    $\begingroup$ @Verde You can take comfort in the fact that 99% is less than 100% :) $\endgroup$
    – rm -rf
    Sep 6 '12 at 23:27
  • $\begingroup$ Ok. I'll take that as it were almost but not quite entirely unlike an insult $\endgroup$ Sep 6 '12 at 23:29
  • $\begingroup$ @Verde Hey, 99% insult is less than 100% insult :D :D $\endgroup$
    – rm -rf
    Sep 6 '12 at 23:29
  • $\begingroup$ @Verde, the sad fact is that there is one person in the world who is completely stupid. $\endgroup$
    – Fred Kline
    Sep 6 '12 at 23:29

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.