How to short-circuit match failure?
- To: mathgroup at smc.vnet.net
- Subject: [mg114229] How to short-circuit match failure?
- From: kj <no.email at please.post>
- Date: Sun, 28 Nov 2010 06:52:25 -0500 (EST)
When defining a function as a sequence of rules (with SetDelayed), I often want to have messages emitted if the arguments do not have the proper form, and then *stop* trying any remaining rules, but I don't know how to do the latter. Here's a silly example: ClearAll[foo] foo::toolong = "List is too long"; foo::nolist = "First argument is not a list"; foo::nargs = "foo called with `1` argument(s); 2 expected"; foo[x_List /; Length[x] < 3, y_] := {#, y} & /@ x foo[x_List, y_] /; Message[foo::toolong] = Null foo[x_, y_] /; Message[foo::nolist] = Null foo[x___] /; Message[foo::nargs, Length[{x}]] = Null The function foo takes as its first argument a list with length no greater than 2. But see what happens when foo[{1, 2, 3}, 3] is evaluated: In[86]:= foo[{1, 2, 3}, 3] During evaluation of In[86]:= foo::toolong: List is too long During evaluation of In[86]:= foo::nolist: First argument is not a list During evaluation of In[86]:= foo::nargs: foo called with 2 argument(s); 2 expected Out[86]= foo[{1, 2, 3}, 3] The result in Out[86] is as desired, but spurious messages were emitted. It's easy to see why. During the evaluation of foo[{1, 2, 3}, 3], *all* the rules associated with foo are tried, even though the third and fourth ones should not be. I can prevent this from happening by letting the second rule's match succeed; e.g. by defining it like this: foo[x_List, y_] := (Message[foo::toolong]; Null) ...but now evaluating foo[{1, 2, 3}, 3] no longer produces the right final result (it produces Null, instead of foo[{1, 2, 3}, 3]). How can I define the second rule for foo so that the third and fourth ones are not tried, while the final value for foo[{1, 2, 3}, 3] remains as foo[{1, 2, 3}, 3]? TIA! ~kj