# Pattern-matching complex numbers as a + bi

I just started working with Mathematica and am toying with pattern matching. There may be something obvious I'm missing in this, but I can't figure it out by myself.

I want to write down a function that takes a complex number as arguments. So f[1 + 2 I] should be a valid input, as well as f[a + b I]. I want, however, to make my function parse this as two numbers of the form a + bi, getting a and b by pattern matching. I made several attempts similar to this:

f[a_ + b_ I] := NSolve[a^2 + b^2 == 1/2 (1 + z), z]
SetAttributes[f, HoldAll]


(I guess the NSolve doesn't matter in this case, but let it there in case it's part of the issue.)

This doesn't work as I planned. Any attempt to call it, like f[1 + 2 I], just echoes itself, but it does work fine when I call it with symbolic arguments, such as f[a + b I].

I guessed this should be due to some difference in the internal representation of symbolic expressions and complex numbers. Indeed, whenever I try to MatchQ[m + n I, a_ + b_ I], it says it's True. But when I try the sorts of MatchQ[Unevaluated[2 + 3 I], a_ + b_ I], it's False.

In trying to figure it out, I asked

FullForm[a + b I]
FullForm[Unevaluated[2 + 3 I]]
FullForm[a_ + b_ I]


and got

Plus[a,Times[Complex[0,1],b]]
Unevaluated[Plus[2,Times[3,\[ImaginaryI]]]]
Plus[Pattern[a,Blank[]],Times[Complex[0,1],Pattern[b,Blank[]]]]


My questions are:

1. Shouldn't the Plus[2,Times[3,\[ImaginaryI]]] match with Plus[Pattern[a,Blank[]],Times[Complex[0,1],Pattern[b,Blank[]]]]?
2. What is the difference between \[ImaginaryI] and Complex[0,1]? I know the first is a symbol as much as \[Alpha] is, and I guess me asking for Unevaluated is preventing it from being cast as a Complex[0,1]. Probably this would be needed for the matching, but I don't know a workaround.
3. Is there a better way to do what I'm attempting with my function?

Thanks!

• Why not simply use Re and Im to get the two parts? – Lukas Lang Sep 12 '20 at 16:32
• Yes, this is a good solution, of course. I should've put more contex to to my question, though: I'm actually doing this as an exercise to learn pattern matching, as I'm completely new to it. I'll edit this in, thanks! – ppln Sep 12 '20 at 16:54

f[a_. + b_ I | Complex[a_, b_]] := {a, b}

You need to catch both the unevaluated form for symbolic work and the evaluated Complex representation for numerical work. Note that the first a_. allows the real part to be omitted so that purely imaginary parts can be matched as well.
• Great, thanks! This works for all instances with an imaginary part, and it sets the real part to zero when I omit it. It doesn't, however, accept a pure real number as the argument. I then extended it as f[a_. + b_ I | Complex[a_, b_] | a_ + b_.] := {a, b}. I didn't simply use a_ as the last pattern because I wanted the imaginary part to be set to zero, and I also trusted that the matching will be tried from left to right and be short-circuited (so, e.g., f[2 + 3 I] matches with a_. + b_ I, and not with a_ + b_.). It worked for some test cases. Does this look OK? – ppln Sep 12 '20 at 17:21
• I don't think you can trust it to short-circuit left to right, but if it works for what you're doing then it's likely fine. If you are expecting arbitrarily mixed real and imaginary input, you are likely better off using Re and Im. – eyorble Sep 12 '20 at 17:41
• I hadn't noticed about the input ordering, thank you! So I'd have to mimick all those patterns changing a for b. And yes, Re and Im are much more straightforward for real use cases. This was just an exercise as I'm trying to get my head around pattern matching and substitution rules. – ppln Sep 19 '20 at 22:30