Mathematica is, typically, be seen as a calculator. But it do has some shine feature.
Take this as an example:
f[x_] = x^2;
is it $f(x)=x^2$ ? yes, but what defines a function? Do we miss something? Oh, the domain!
so it can be in $\mathbb{C}$ , but you know, in real world, there aren’t just number, we have more things other than that. For example, String
.
f["12"]
get what? oh, "12"^2
, what’s what?
So why does this happen? Because the pattern Blank[]
, aka _
in x_
can accept anything. And mma will hold the expression. (calculate a[b]
and mma will return itself.
So how do we know the type? In mma, we have Head
, Since mma store the 0th element as it’s type. And we can match it with Blank[]
Clear[f];
f[x_Integer]=x^2;
f["12"]
f[12]
Typed based overload.
But it’s much powerful than that.
we can double anything!
double[x_Integer] = x^2;
double[x_String] := x <> x;
double[x_] = {x,x};
double[1]
double["1"]
double[1+2I]
:=
because StringJoin
need to calculate the expression at once. So we need to delay it.
But if I want to double any number?
notice the difference between
NumericQ
andNumberQ
,NumberQ[Sqrt[2]]
return False.
Clear[double];
double[x_?NumericQ] = x^2;
double[x_String] := x <> x;
double[x_] = {x,x};
double[1]
double["1"]
double[1+2I]
in some aspect, we can think
_?NumericQ
as aProtocal
orInterface
orTrait
.(For example,num-traits
in rust.
So, if you want to match a/some certain type(s), use _X
or _X|_Y
, else use _?XQ
.