# How to define a parameter with both Optional and PatternTest

Why this doesn't work?

k[x_Integer:2?(#>0&)]:=x^2
k[]  (*should be 4*)
k (*should be 4*)


These following are all working as expected:

(* with Optional *)
f[x_Integer:2]:=x^2
f[]
(* with PatternTest *)
g[x_Integer?(#>0&)]:=x^2
g
(* with Optional + Condition *)
h[x_Integer:2]:=x^2/;x>0
h[]
h

• ClearAll[k]; k[x : _Integer?(# > 0 &) : 2] := x^2? – kglr Aug 29 at 17:12
• That can also be written as k[x : _Integer?Positive : 2] := x^2 – Bob Hanlon Aug 29 at 17:16
• ... or ClearAll[k2];k2[Optional[x_Integer?Positive, 2]] := x^2 – kglr Aug 29 at 17:16
• see k[x_Integer: 2?(# > 0 &)] // FullForm and Precedence /@ {Optional, Pattern, PatternTest} – kglr Aug 29 at 17:18

It doesn't work because : can have two meanings in an argument form, Optional and Pattern, and the front-end has trouble deciding which is meant when two : appear in such an argument.

You can fix the issue by writing Optional in full form. Like so:

Clear[k]; k[Optional[x_Integer?Positive, 2]] := x^2; {k[], k, k[-2], k[2.]


{4, 4, k[-2], k[2.]}

You might also want to consider some alternatives.

Clear[k]; k[x_Integer : 2] /; x > 0 := x^2
Clear[k]; k[x_ : 2] /; x ∈ PositiveIntegers := x^2
Clear[k]; Default[k] = 2; k[x_.] /; x ∈ PositiveIntegers := x^2