Skip to main content

programming - How can I type-check the arguments of a Mathematica function?


(For educational purposes) I defined the following functions:


Translation (in $\mathbb{R}^2$):


trM[vec_] := {{1, 0, vec[[1]]}, {0, 1, vec[[2]]}, {0, 0, 1}}

Rotation (in $\mathbb{R}^2$):



rotM[angle_] := {{Cos[angle], -Sin[angle], 0}, {Sin[angle], Cos[angle], 0}, {0, 0, 1}}

Rotation around a point (in $\mathbb{R}^2$):


rotM[pt_, angle_] := trM[pt].rotM[angle].trM[-pt]

So far so good, now I want a function:


rotM[angle_, n_] := 
{{Cos[n angle], -Sin[n angle], 0}, {Sin[n angle], Cos[n angle], 0}, {0, 0, 1}}

Now



 rotM[angle_, n_] 

and


rotM[pt_, angle_] 

share — in Mathematica — the same signature, which breaks the polymorphism I intended to use, which then leads to the following question.


How can I type-check the arguments of a Mathematica function to enforce polymorphism?



Answer



At a minimal level you could discriminate like this


f[angle_ n_] := ...

f[pt : {_, _}, angle_] := ...

But if you want to be really picky, you could limit your pt argument to only except a list of two elements, both of which are numeric objects, but neither of which is a complex number. This can be done by defining a new argument pattern


pt2D = {Repeated[Except[_Complex, _?NumericQ], {2}]};

and using the pattern in a function definition such as


f[v : pt2D] := v

then


pts = {{1, 2}, {1., 2.}, {1., 2}, {1, π}, 1, {1}, {1, I}, {1, 2, 3}};

f /@ pts

gives



{{1, 2}, {1., 2.}, {1., 2}, {1, π}, f[1], f[{1}], f[{1, I}], f[{1, 2, 3}]}

Note both the wide acceptance of forms that have the structure of 2D points and the rejection of forms that don't.


Comments