Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

EDIT: As several respondents have noted in the answers and comments below, the original example had a default value that would never be used because of the way patterns and default values are applied. I've edited the example so that it now focuses on the question that was being asked and which has already been answered.

Is it possible to achieve the following behavior in a function definition:

Remove[foo];
foo[Optional[Pattern[x, _?IntegerQ], 1]] := x;
foo[]
foo[2]

1
2

using "colon syntax" shorthand?

Note that,

Remove[foo];
foo[x : _?IntegerQ : 1] := x;
foo[] 
foo[2] 

foo[]
foo[2]

does not produce the desired result.

The first code sample is too verbose; setting a default value for a function argument while simultaneously checking type when an argument is supplied should be common enough practice to deserve its own shorthand notation.

Can anyone modify the second example to achieve the desired results? If Mathematica syntax does not directly support shorthand for combining default values with argument type checking, perhaps someone could suggest how this might be achieved using the Notation package.

share|improve this question
3  
Note that, in your formulation, defaults will be never used (so it's not quite clear to me why bother with them then), and so in all the answers so far. In case you do want to use the default, there is a subtlety here, because the default must match the general pattern, to be used. More details are here –  Leonid Shifrin May 1 '12 at 8:27
1  
Thanks for the link and for highlighting this important subtlety regarding how pattern matching and default values work together. I edited the original question to reflect your input. –  StackExchanger May 1 '12 at 20:17
    
@R.M. In this particular case, this is important, because there are (at least) 2 different subtleties associated with this construction, and we don't want to discuss one of them using an example where another one is also broken. –  Leonid Shifrin May 1 '12 at 20:41
    
@LeonidShifrin I agree. –  rm -rf May 1 '12 at 21:08

1 Answer 1

up vote 18 down vote accepted

Perhaps this?

foo[x : (_?IntegerQ) : 1] := x;

foo[]
foo[7]
foo["string"]
1
7
foo["string"]

As Leonid reminds, if the default value does not match the test function it will not be returned. To allow for this you can explicitly include the value in the pattern:

ClerAll[foo]
foo[x : (_?IntegerQ | "default") : "default"] := x;

foo[]
foo[7]
foo["string"]
"default"
7
foo["string"]

In the comments magma makes an excellent point. You can use multi-clicking, or as I prefer Ctrl+. to examine parsing. See this answer.

share|improve this answer
    
Thanks -- I tried different parentheses because I wan't sure about the relative precedence of the colons and the underscore binding to the pattern test but missed this possible grouping. –  StackExchanger May 1 '12 at 3:27
2  
In general you can use multiple clicking to see how binding works –  magma May 1 '12 at 8:59
    
@magma Great tip ... I was just about to ask if there was a way to expose the binding rules being used in a given expression. This will be helpful for troubleshooting future issues involving relative precedence. –  StackExchanger May 1 '12 at 19:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.