Re: Implicit Times
- To: mathgroup at smc.vnet.net
- Subject: [mg128669] Re: Implicit Times
- From: awnl <awnl at gmx-topmail.de>
- Date: Thu, 15 Nov 2012 03:58:55 -0500 (EST)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- Delivered-to: l-mathgroup@wolfram.com
- Delivered-to: mathgroup-newout@smc.vnet.net
- Delivered-to: mathgroup-newsend@smc.vnet.net
- References: <k7hh3j$nv1$1@smc.vnet.net>
Hi, > Mathematica assumes Times (*) when two expressions are > juxtaposed with no explicit intervening binary operator > (ex., x y is interpreted as x*y). > I want to change this behavior so it assumes a > NonCommutativeMultiply (**) instead. > Is this possible? It is possible, but I'd hardly recommend to do it, it is probably just as dangerous as overwriting important internal symbols like Times. What you want to do is interfering with Mathematica at a very deep level so be warned to be cautious when playing with these things: errors at that level might crash or hang the Kernel, the FrontEnd or even the OS (at least a Windows box). AFAIK there are two possible approaches, either you can use the hook $PreRead to manipulate the boxes before parsing (and $Pre to manipulate the unevaluated input) or use MakeExpression which lets you redefine how boxes are converted to expressions. I think it is somewhat easier to use $PreRead and $Pre for what you need and found MakeExpression even more dangerous than those, so I'll stick with $PreRead and $Pre in the following. You should also note that this approach might need some changes when you want it to work with InputForm strings as e.g. when reading package files. What I'll show will in this form only work in the notebook interface. Even though the mentioned functions let you manipulate the boxes at a very early stage of the evaluation process, the conversion of spaces has already been done, as you can learn from the documentation (tutorial/LowLevelInputAndOutputRules) and verify with this: $PreRead=Function[Print[#];#]; a*b c**d $PreRead=.; Nevertheless, building on David Baileys tricks with interpreting strings we can apply the same strategy to manipulate the boxes, but we have to take special care to not evaluate too early which makes the following somewhat lengthy. The following definitions will basically do what you want: $PreRead = Function[ Function[x, MakeBoxes[x, StandardForm], HoldAllComplete] @@ ( MakeExpression[# /. "*" -> "\[Star]", StandardForm] /. Times -> NonCommutativeMultiply )]; $Pre = Function[Null, ReleaseHold[HoldComplete[#] /. Star -> Times], HoldAllComplete]; a (a b)*(c a) I'm using "\[Star]" as a temporary substitute for "*" here, which looks exactly like "*" in a notebook but has the advantage that it's precedence is such that no extra care needs to be taken to keep the precedence between ** and * (see tutorial/OperatorInputForms in the documentation for information on operator precedence). If at all I would only switch this on temporarily where needed, so as soon as not needed anymore you should evaluate: $PreRead = .; $Pre = .; If you really want to use such an approach, I'd recommend to define helper functions as e.g.: beginncm[] := ( $PreRead = Function[ Function[x, MakeBoxes[x, StandardForm], HoldAllComplete] @@ ( MakeExpression[# /. "*" -> "\[Star]", StandardForm] /. Times -> NonCommutativeMultiply )]; $Pre = Function[Null, ReleaseHold[HoldComplete[#] /. Star -> Times], HoldAllComplete]; ); endncm[] := ($PreRead =.; $Pre =.;); so that you can temporarily switch on the desired behavior without too much risk of breaking other things: beginncm[] expr = a (a b)*(c a); endncm[] you will find that this approach has some subtle problems, but it probably is good enough to define expressions with your prefered syntax. One of the problems I observed was that e.g. wrappers like FullForm don't work as expected. The reason for tis is that MakeBoxes[MakeExpression[#]]& isn't an exact identity (MakeExpression does obviously does strip some of these wrappers). There could of course be other side effects that I didn't happen to observe... hth, albert