In writing my own (noncommutative) product I want to avoid typing redundant symbols like A.B.C or A**B**C, I just want to type A B C and have that mapped to my own Product[A,B,C]. (call me a purist)

1. Is there a clever way to avoid A B C being mapped to Times[A,B,C] (besides ClearAll[Times])?

2. Is there any documentation about the inner workings of (Pre-)Parsing and Times?

  • 2
    $\begingroup$ Why do you think ClearAll[Times] would work? $\endgroup$ – rm -rf Sep 29 '12 at 18:00
  • $\begingroup$ It will not. That was just a rhetoric side note. $\endgroup$ – NoEscape Sep 30 '12 at 5:36
  • $\begingroup$ @rm-rf : please note, this is a Q&A site, not a Q&Q site!!! $\endgroup$ – NoEscape Oct 1 '12 at 17:14
  • $\begingroup$ @NoEscape but the FAQ says that comments should be used to help clarify the questioner's thoughts... So this is a Q, C, and A site really... $\endgroup$ – cormullion Oct 1 '12 at 17:28

What I usually suggest for such cases is to use custom environments, inside which you can change the rules of the game. Here is a lexical one for your case:

SetAttributes[withNCTimes, HoldAll];
withNCTimes[code_] :=
    Unevaluated[code] /. Times -> NonCommutativeMultiply

so that


(*  a**b**c  *)

and here is the dynamic one:

SetAttributes[withNCTimesDyn, HoldAll];
withNCTimesDyn[code_] :=
  Block[{Times =  NonCommutativeMultiply},

which would, for the example above, produce the same result.

Dynamic environments are more dangerous since they affect the full evaluation stack, but also more general. Lexical environments are safer, since their action is lexically localized to code you have inside of them. But, if that code contains function calls where Times is used, those invocations of Times won't be affected by the environment, since they are not literally present in the piece of code around which you wrap the environment. I discussed this in a little more detail here.

If you don't want to type the name of an environment every time, you can, in the FrontEnd session, automate that by utilizing $Pre:

$Pre = withNCTimes;

(* a**b**c *)

$Pre =. 

Finally, I would never attempt to overload Times (or Plus etc), since these functions are very fundamental to the system, and there is no telling what can happen if you do that. Even for more specialized functions, their overloading can lead to quite strange and unwanted behavior, see e.g. here.

| improve this answer | |
  • $\begingroup$ @rm-rf It must be possible along the same lines as in my answer above, just more complicated rules. $\endgroup$ – Leonid Shifrin Sep 29 '12 at 20:16
  • $\begingroup$ @ rm-rf: My comment was just intended to mean that I'm still going to to use Times, as for example MyProduct[A,b,C] will be converted to Times[b,MyProduct[A,C] if b is a Number or has a Scalar property. so, i still need Times - internally - not in input => i cannot modify Times to always map to MyProduct because this will lead to recursion $\endgroup$ – NoEscape Sep 30 '12 at 5:00
  • $\begingroup$ thx^2 to Leonid, your answer just opened a door for me! $\endgroup$ – NoEscape Sep 30 '12 at 5:01
  • $\begingroup$ Thx for mentioning the $Pre=. command. It should also be put before the lines ClearAll[withNCTimes]; or ClearAll[withNCTimesDyn]; in the code above, otherwise all input will be messed up if the definitions are executed a second time. $\endgroup$ – NoEscape Sep 30 '12 at 5:32
  • 1
    $\begingroup$ @NoEscape It is probably possible. Conceptually, it is also better, because what you basically want is to change the syntax. However, all these approaches are incomplete. Generally you want something like a programmable language preprocessor, which Mathematica does not have. I discussed these matters in a little more detail in my answer here. $\endgroup$ – Leonid Shifrin Oct 1 '12 at 13:16

I would strongly recommend that you not follow this approach. It is not a good idea to modify built-ins, especially something as fundamental as Times as this could lead to unintended consequences elsewhere. Instead, I would suggest that you utilize one of the many infix operators without any pre-defined meaning.

That said, you could do something like:

Times[x__Symbol] := MyProduct[x]

(* MyProduct[X, Y, Z] *)

This acts only on symbols, so multiplication of numbers and variables with OwnValues still work as usual.

| improve this answer | |
  • $\begingroup$ Right, I'm trying to avoid modifying Times[], as you recommend and as it is self-evident. (I'm a novice to StackExchange, not to programming) E.g. I still want to use Times[a,MyProduct[A,B]] for certain a's, which will besome impossible/recursive with your code. $\endgroup$ – NoEscape Sep 29 '12 at 19:13
  • $\begingroup$ I need something that acts on the notation/input side only. Like Notation[ [a_ b_ c_] <=> MyProduct[a_,b_,c_] ], but this will not work, because the internal Times Notation is at work FIRST! $\endgroup$ – NoEscape Sep 29 '12 at 19:25
  • $\begingroup$ @NoEscape Times is one of the few functions where built-ins definitions are always read first before custom definitions. This is in the "More info" section of the docs. As such, I highly doubt it might be possible to do something along the lines of what you want... I could be wrong, but it's beyond me. $\endgroup$ – rm -rf Sep 29 '12 at 19:33
  • $\begingroup$ @rm-rf Well, sometimes things like this are possible. I am not sure though I'd recommend that. $\endgroup$ – Leonid Shifrin Sep 29 '12 at 20:02

I'm not sure how useful this is in your redundancy-free setting or at all, but I assume you don't want the non-commutative multiplication to happen everywhere. When you wrap your special data-type like for instance this M[data] than another approach would be possible

M /: Times[M[a_], M[b_]] := M[MyProduct[a, b]]

and you get the special multiplication only for your special data-structure

Mathematica graphics

You maybe shouldn't use M but something like \[ScriptCapitalM] which you can input fast but which is less likely to be already defined.

| improve this answer | |
  • $\begingroup$ Already tried a similar thing. This will immediately fail if someone types M[a] A M[b], so we'd have to define all kinds of combos... $\endgroup$ – NoEscape Sep 30 '12 at 9:38

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.