I have an expression involving several dot products, I give a simplified example:


I want to reverse all dot products, and try

expr/.Dot[x__]:> Reverse[Dot[x]]

which returns {C.D,A.B}, i.e., Reverse operates on the first level of expr, not of its argument. If I write


in the command above I do get the desired {B.A,D.C}, i.e., now Reverse operates on the second level of expr. This only works because all dot products in expr are at the same level, which is not the case in my original problem.

I have two questions:

  1. How to explain the above behavior of Reverse?
  2. How to accomplish the reversal of the order of the dot products when scattered at various levels within an expression?
  • 2
    $\begingroup$ Patter matching comes to the rescue: {{{a . b}}, {c . d}} /. Dot[x_, y_] -> Dot[y, x] $\endgroup$ Feb 3, 2022 at 16:53
  • $\begingroup$ The problem is that Dot[x__] evaluates to x__. You need to use HoldPattern to prevent this, although @lericr's answer is much cleaner. $\endgroup$
    – Carl Woll
    Feb 3, 2022 at 18:09
  • $\begingroup$ Many thanks to @lericr and @carlwoll for the answer, and to @ben for formatting the question. The suggestion by @danielhuber works for two arguments in Dot (or a given fixed number), which is not the case in my problem (I get dot products of various numbers of arguments) - I guess one could always write a list of substitutions for two, three, etc arguments. $\endgroup$ Feb 4, 2022 at 4:17
  • $\begingroup$ @ChryssomalisChryssomalakos Try with MapAt[Reverse, tensor, level]. Put level = {All} when TensorRank[tensor] = 1, level={All, All} when TensorRank[tensor] = 2 and so on. You can build a function for that. $\endgroup$ Feb 4, 2022 at 6:22

1 Answer 1


First I'll provide a solution, second I'll explain the results you got.

  1. The better solution is to match on the expression that you want to reverse:

    expr /. dot_Dot :> Reverse[dot]

    This will do the replacement at every level in the expression.


original explanation is wrong

  1. Why did your original attempt behave so strangely? The left side or your rule was Dot[x__], and what that means is "find all expressions, one or more elements long, that find themselves inside a Dot-headed expression, and name them 'x'". Well, all of A, B, C, and D match that pattern. And preserving their relative structure, what the replacement rule did was generate

    Reverse[Dot[{A . B, C . D}]]

    Because of the semantics of Dot, this is just

    Reverse[{A . B, C . D}]

    and you can see where it went from there.


[Edit based on Carl Woll's comment: Yeah, the Dot[x__] is actually evaluated, so your rule is actually x__ :> Reverse[Dot[x]]]

  1. Why did your original attempt behave so strangely? The left side or your rule was Dot[x__], which evaluates to just x__, and so your rule matches the entire expression. et cetera
  • $\begingroup$ Your point 2 is confusing. The issue is just that Dot[x__] evaluates to x__ $\endgroup$
    – Carl Woll
    Feb 3, 2022 at 18:10
  • $\begingroup$ yep. that was lame. I was thinking it was pattern matching on the head (but that would have been _Dot). I should have just used Trace to see what was going on rather than tie myself up in pattern matching knots. $\endgroup$
    – lericr
    Feb 3, 2022 at 22:15

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.