5
$\begingroup$

Why this doesn't work?

k[x_Integer:2?(#>0&)]:=x^2
k[]  (*should be 4*)
k[2] (*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[2]
(* with Optional + Condition *)
h[x_Integer:2]:=x^2/;x>0
h[]
h[2]
$\endgroup$
4
  • 4
    $\begingroup$ ClearAll[k]; k[x : _Integer?(# > 0 &) : 2] := x^2? $\endgroup$
    – kglr
    Aug 29, 2020 at 17:12
  • 2
    $\begingroup$ That can also be written as k[x : _Integer?Positive : 2] := x^2 $\endgroup$
    – Bob Hanlon
    Aug 29, 2020 at 17:16
  • $\begingroup$ ... or ClearAll[k2];k2[Optional[x_Integer?Positive, 2]] := x^2 $\endgroup$
    – kglr
    Aug 29, 2020 at 17:16
  • 2
    $\begingroup$ see k[x_Integer: 2?(# > 0 &)] // FullForm and Precedence /@ {Optional, Pattern, PatternTest} $\endgroup$
    – kglr
    Aug 29, 2020 at 17:18

1 Answer 1

2
$\begingroup$

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[2], 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
$\endgroup$

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.