I am trying to implement the creation and annihilation operators $\hat{a}$ and $\hat{a}^{\dagger}$ of quantum mechanics with the following code, but alas, there is a problem with the pattern matching for the leading coefficient $cc\_$. Any idea on how to fix this? I tried $cc\_:1$, but that didn't work.

Clear[a, adag, cc, ketk, nn]; (* Choosing nn and cc to avoid name collisions *)
a[cc_ ketk_Ket] := With[{nn = ketk[[1]]}, cc Sqrt[nn] Ket[nn - 1]];
adag[cc_ ketk_Ket] := With[{nn = ketk[[1]]}, cc Sqrt[nn + 1] Ket[nn + 1]];

When I try give Ket[0], i.e., $3|1\rangle$, to adag, I get back adag[Ket[0]], but if there is a leading coefficient, then the pattern match works. For example, adag[3 Ket[0]] returns 3 Ket[1], i.e., $3|1\rangle$ . I think this shows my code doesn't know what to do for the first case in terms of matching.


4 Answers 4


When in doubt about the interpretation of a pattern (especially involving operations such as Times with special Attributes), it's best to specify the desired pattern in FullForm instead of StandardForm, because it removes ambiguities.

For your case, the desired FullForm version with the optional argument for the scalar factor would be

Clear[a, adag, cc, ketk, nn];(*Choosing nn and cc to avoid name collisions*)
a[Times[cc_: 1, ketk_Ket]] := 
 With[{nn = ketk[[1]]}, cc Sqrt[nn] Ket[nn - 1]];
adag[Times[cc_ : 1, ketk_Ket]] := 
  With[{nn = ketk[[1]]}, cc Sqrt[nn + 1] Ket[nn + 1]];

Now you get the expected results:


(* ==> Ket[1] *)

adag[2 Ket[0]]

(* ==> 2 Ket[1] *)

By using Times explicitly, I make sure that Mathematica knows what part of the expression is to be parsed as the option value. If you don't do this, the expression is misunderstood:

FullForm[g[cc_: 1 ketk_Ket]]


What happened here is that the Optional value was taken to be 1 ketk_Ket which evaluates to ketk_Ket. That's of course not what you wanted, it's just a consequence of operator precedence here. You could also have fixed this by using parentheses in the StandardForm pattern you tried originally, but using FullForm is usually clearer.

In some cases one also has to protect the pattern from simplifying by using HoldPattern, but that's not needed in this application.

  • $\begingroup$ Thanks a lot, that really helps! $\endgroup$
    – Frank
    Commented Dec 31, 2015 at 3:44

May be (if I understand you correctly) you can add a default value for arguments:

Default[a] = 1;
Default[adag] = 1;

and then change the functions argument in the definition to:

a[cc_. ketk_Ket] :=....
adag[cc_. ketk_Ket] :=....

I think it should be noted that follow forms of definition will work.

a[(cc_:1) ketk_Ket] := With[{nn = ketk[[1]]}, cc Sqrt[nn] Ket[nn - 1]]


adag[(cc_:1) ketk_Ket] := With[{nn = ketk[[1]]}, cc Sqrt[nn + 1] Ket[nn + 1]]



Does Mathematica support Polymorphism ? Yes, at least function overloadingit does. I have stripped your methods a bit,

adag[cc_ ketk_Ket] := With[{nn = ketk}, {cc, nn} ]    
adag[ketk_Ket] := With[{nn = ketk, cc = 1}, {cc, ketk} ]


adag[Ket[3]] => {1, Ket[3]}
adag[2*Ket[4]] => {2, Ket[4]}

Or you can use default arguments as suggested above. But its helpful in scenarios where overloading cannot be escaped.


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.