二項演算子の引数が1つのとき
a**b**c
はNonCommutativeMultiply[a,b,c]
の略記であり,またNonCommutativeMultiply
の属性Flat
のためにa**(b**c)
等とも同値である.NonCommutativeMultiply
には属性OneIdentity
も設定されているため,NonCommutativeMultiply
の引数をパタンマッチで取り出すとき,取り出した結果には自動的にNonCommutativeMultiply
が頭部として付く.a**(b**c)
が常にa**b**c
に読み替えられるならば,NonCommutativeMultiply[a,b,c]
のb,c
部分を取り出したとき,それは元々b**c
だったのかもしれない訳で,そういう扱いが属性OneIdentity
の役割である.
さて**
が二項演算子だと思うとNonCommutativeMultiply[a_]:=a
は自然である.しかしこれが属性OneIdentity
と組み合わさると,NonCommutativeMultiply
の引数を取り出したつもりが,得たa
にはNonCommutativeMultiply[a]
が入ってくるため,無限ループになってしまう.これはどうしたものか... ClearAttributes
を使ってOneIdentity
を除いても振る舞いが変わらない! (Attributes
によれば確かに消えているのに! Times[a]
はひとりでにa
に等しくなるのに!)
これじゃtensor積の実装で困る.無論,入力するときには**
を常に使うと思うとNonCommutativeMultiply[a]
の形の式は現れない.しかしNonCommutativeMultiply[a__,e1_] NonCommutativeMultiply[e2_,b__]:=e1 e2 NonCommutativeMultiply[a] NonCommutativeMultiply[b]
のようにするとNonCommutativeMultiply[a]
の形の式が現れてしまう.昨日は愚直にa_**e1_ e2_**b_:=e1 e2 a b /;FreeQ[e1,NonCommutativeMultiply]∧FreeQ[e1,NonCommutativeMultiply]
とやったらうまく行った.