Mathematica 9 is now available
Services & Resources / Wolfram Forums / MathGroup Archive
-----

MathGroup Archive 2010

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: How to short-circuit match failure?

  • To: mathgroup at smc.vnet.net
  • Subject: [mg114344] Re: How to short-circuit match failure?
  • From: kj <no.email at please.post>
  • Date: Wed, 1 Dec 2010 02:14:38 -0500 (EST)
  • References: <ictfq8$mck$1@smc.vnet.net> <id01ld$h6o$1@smc.vnet.net>

Thanks for all your comments and suggestions.  Inspired by them,
I came up with this general approach for defining a function that
emits diagnostic messages when called with incorrect arguments,
and returns the original expression (unevaluated).

The idea is to replace something like this:

ClearAll[foo]
foo::toolong = "First argument 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[_List, _] /; Message[foo::toolong] = Null
foo[_, _] /; Message[foo::nolist] = Null
foo[x___] /; Message[foo::nargs, Length[{x}]] = Null

with something like this:

ClearAll[foo]
foo::toolong = "First argument is too long";
foo::nolist = "First argument is not a list";
foo::nargs = "foo called with `1` argument(s); 2 expected";
foo[args___] := Module[{chkargs, argsok, core, othervars},
  
  chkargs[x_List /; Length[x] < 3, y_] := True;
  
  chkargs[_List, _] := Message[foo::toolong]; 
  chkargs[_, _] := Message[foo::nolist]; 
  chkargs[x___] := Message[foo::nargs, Length[{x}]];
  
  core[x_, y_] := {#, y} & /@ x;
  
  argsok = chkargs[args];
  argsok && core[args] /; argsok
  ]

The function is defined as a *single* (delayed) rule that evaluates
to a module with a standard structure.  The key points are these:

1. the rule has a single catchall pattern (args___), and therefore
   it will apply to all invocations of the function;

2. all the argument-checking is transferred basically verbatim to
   a module-local rule called checkargs; this rule evaluates to
   True whenever the arguments are valid, or to a call to Message
   with the appropriate diagnostic; this terminates the argument-checking,
   so any remaining chkargs rules are skipped;

3. the function's main action (which assumes all the arguments are
   ok) is defined as one or more module-local delayed rules called
   core; since all the argument matching and checking is delegated
   to the chkargs rule(s), the pattern(s) for the core rule(s) can
   be more general (i.e. simpler) than would be required otherwise
   (e.g. in the example above, the pattern is simply x_, y_);

4. the last two lines of the module are standard (always the same);
   in the next-to-last line, argument checking is done by evaluating
   chkargs[args} and assigning the reuslt to the module-local
   variable argsok; in the process, diagnostic messages are emitted
   if the checking fails; in this case, argsok will have value
   Null; otherwise, it will have value True;

5. in the last line, if argsok is True, core[args] is evaluated,
   and returned as the module's evaluation value; if argsok is not
   True (i.e.  it is Null), core[args] is not evaluated, and
   furthermore the main module's evaluation will fail thanks to
   the failed /; argsok condition at the end, so the final evaluation
   will yield the original expression, unevaluated;

6. one feature not illustrated by the simple example above is that
   the DownValues of the chkargs rules can be more elaborate, and
   even set the process of variables local to the main module
   (represented by othervars in the example); these variables can
   be shared with other chkargs rules, or core rules, and thus
   avoid having to perform some calculations needed by several of
   them more than once.

This approach seems pretty general to me, and it is basically a
wrapper around the "standard" approach.

As always, your comments and criticisms are always welcome.

~kj


  • Prev by Date: Re: Difficulty in obtaining a numerical solution for a partial
  • Next by Date: Re: Finding local maxima in multidimensional array (efficiently)
  • Previous by thread: Re: Difficulty in obtaining a numerical solution for a partial
  • Next by thread: Re: How to short-circuit match failure?