Skip to main content
replaced http://mathematica.stackexchange.com/ with https://mathematica.stackexchange.com/
Source Link

To do this using PatternTest we would need to apply it to the entire expression f3[x__], complicating its form and risking unwanted evaluation or recursion. (Counterexample: see my proposed solution to Quick way to use conditioned patterns when defining multi-argument function?Quick way to use conditioned patterns when defining multi-argument function? for where I feel that PatternTest is the best way to proceed.)

LeonidLeonid wrote, and encouraged me to include here:

One other thing I want to mention is that with PatternTest, it is easier to inadvertently leak evaluation, while in Condition avoiding that is usually just a matter of inserting Unevaluated in a proper place. I discussed this topic to some extent herehere

Finally, there are some syntactic differences which are good to keep in mind, for example precedence-related issues like this onethis one.

To do this using PatternTest we would need to apply it to the entire expression f3[x__], complicating its form and risking unwanted evaluation or recursion. (Counterexample: see my proposed solution to Quick way to use conditioned patterns when defining multi-argument function? for where I feel that PatternTest is the best way to proceed.)

Leonid wrote, and encouraged me to include here:

One other thing I want to mention is that with PatternTest, it is easier to inadvertently leak evaluation, while in Condition avoiding that is usually just a matter of inserting Unevaluated in a proper place. I discussed this topic to some extent here

Finally, there are some syntactic differences which are good to keep in mind, for example precedence-related issues like this one.

To do this using PatternTest we would need to apply it to the entire expression f3[x__], complicating its form and risking unwanted evaluation or recursion. (Counterexample: see my proposed solution to Quick way to use conditioned patterns when defining multi-argument function? for where I feel that PatternTest is the best way to proceed.)

Leonid wrote, and encouraged me to include here:

One other thing I want to mention is that with PatternTest, it is easier to inadvertently leak evaluation, while in Condition avoiding that is usually just a matter of inserting Unevaluated in a proper place. I discussed this topic to some extent here

Finally, there are some syntactic differences which are good to keep in mind, for example precedence-related issues like this one.

added 283 characters in body
Source Link
Mr.Wizard
  • 273.1k
  • 34
  • 595
  • 1.4k

I can think of no way toTo do this with PatternTestusing PatternTest we would need to apply it to the entire expression f3[x__], complicating its form and risking unwanted evaluation or recursion. (Because as stated above each element ofCounterexample: see my proposed solution to Quick way to use conditioned patterns when defining multi-argument function? for where I feel that PatternTest is the sequence is tested independentlybest way to proceed.)

I can think of no way to do this with PatternTest. (Because as stated above each element of the sequence is tested independently.)

To do this using PatternTest we would need to apply it to the entire expression f3[x__], complicating its form and risking unwanted evaluation or recursion. (Counterexample: see my proposed solution to Quick way to use conditioned patterns when defining multi-argument function? for where I feel that PatternTest is the best way to proceed.)

attempt to clarify statement
Source Link
Mr.Wizard
  • 273.1k
  • 34
  • 595
  • 1.4k

I usually consider PatternTest as local to a specific pattern such as x_Integer?Positive and Condition as more general, often involving multiple patterns, e.g.:

f[x_, y_] /; x+y < 10 := x*y

An aspect of PatternTest that is different from Condition is that it is automatically applied to each element of a sequence, whereas Condition applies to the whole. A pattern such as __?EvenQ means a sequences of arguments all of which pass EvenQ. Consider:

f2[x__?EvenQ] := . . .

This is awkward with Condition:

f1[x__] /; (And @@ EvenQ /@ {x}) := . . .

Furthermore the naive method above does not short-circuit on a failure therefore it will be inefficient. This could be fixed but it will be even more clumsy.

Then consider the converse:

f3[x__] /; Plus[x] == 7 := . . .

I can think of no way to do this with PatternTest. (Because as stated above each element of the sequence is tested independently.)

There is one rather obscure (at least to me) yet very important use of Condition that extends this generality.

lhs := Module[{vars}, rhs /; test] allows local variables to be shared between test and rhs. You can use the same construction with Block and With.

This is quite unusual in Mathematica's patterns and assignments. It allows execution of code as part of the definition, then testing by a condition based on the result. If the condition fails, the pattern matcher then moves on to search for other matches. The evaluation that occurred can produce side effects but otherwise Mathematica behaves as though the entire pattern (lhs := rhs assignment) did not match.

One elegant use of this functionality is the Trott-Strzebonski method for In-Place Evaluation.


Leonid wrote, and encouraged me to include here:

One other thing I want to mention is that with PatternTest, it is easier to inadvertently leak evaluation, while in Condition avoiding that is usually just a matter of inserting Unevaluated in a proper place. I discussed this topic to some extent here

Finally, there are some syntactic differences which are good to keep in mind, for example precedence-related issues like this one.


Rojo stated:

Another consequence of this shows when you want to store a pattern in a variable, or inject it with a With. ... Can't do that with Condition unless you want all the instances of the pattern in each definition to be the same.

As a rather contrived counter-example one can use Unique symbols in a pattern constructor:

pat[] := Pattern[#, _] /; # > 4 & @ Unique[]

f[a : pat[], b : pat[]] := {a, b}

f[5, 6]

{5, 6}

Of course it is better to use PatternTest for this, but I think it is useful to show that it can be done.

I usually consider PatternTest as local to a specific pattern such as x_Integer?Positive and Condition as more general, often involving multiple patterns, e.g.:

f[x_, y_] /; x+y < 10 := x*y

An aspect of PatternTest that is different from Condition is that it is automatically applied to each element of a sequence, whereas Condition applies to the whole. A pattern such as __?EvenQ means a sequences of arguments all of which pass EvenQ. Consider:

f2[x__?EvenQ] := . . .

This is awkward with Condition:

f1[x__] /; (And @@ EvenQ /@ {x}) := . . .

Furthermore the naive method above does not short-circuit on a failure therefore it will be inefficient. This could be fixed but it will be even more clumsy.

Then consider the converse:

f3[x__] /; Plus[x] == 7 := . . .

I can think of no way to do this with PatternTest.

There is one rather obscure (at least to me) yet very important use of Condition that extends this generality.

lhs := Module[{vars}, rhs /; test] allows local variables to be shared between test and rhs. You can use the same construction with Block and With.

This is quite unusual in Mathematica's patterns and assignments. It allows execution of code as part of the definition, then testing by a condition based on the result. If the condition fails, the pattern matcher then moves on to search for other matches. The evaluation that occurred can produce side effects but otherwise Mathematica behaves as though the entire pattern (lhs := rhs assignment) did not match.

One elegant use of this functionality is the Trott-Strzebonski method for In-Place Evaluation.


Leonid wrote, and encouraged me to include here:

One other thing I want to mention is that with PatternTest, it is easier to inadvertently leak evaluation, while in Condition avoiding that is usually just a matter of inserting Unevaluated in a proper place. I discussed this topic to some extent here

Finally, there are some syntactic differences which are good to keep in mind, for example precedence-related issues like this one.


Rojo stated:

Another consequence of this shows when you want to store a pattern in a variable, or inject it with a With. ... Can't do that with Condition unless you want all the instances of the pattern in each definition to be the same.

As a rather contrived counter-example one can use Unique symbols in a pattern constructor:

pat[] := Pattern[#, _] /; # > 4 & @ Unique[]

f[a : pat[], b : pat[]] := {a, b}

f[5, 6]

{5, 6}

Of course it is better to use PatternTest for this, but I think it is useful to show that it can be done.

I usually consider PatternTest as local to a specific pattern such as x_Integer?Positive and Condition as more general, often involving multiple patterns, e.g.:

f[x_, y_] /; x+y < 10 := x*y

An aspect of PatternTest that is different from Condition is that it is automatically applied to each element of a sequence, whereas Condition applies to the whole. A pattern such as __?EvenQ means a sequences of arguments all of which pass EvenQ. Consider:

f2[x__?EvenQ] := . . .

This is awkward with Condition:

f1[x__] /; (And @@ EvenQ /@ {x}) := . . .

Furthermore the naive method above does not short-circuit on a failure therefore it will be inefficient. This could be fixed but it will be even more clumsy.

Then consider the converse:

f3[x__] /; Plus[x] == 7 := . . .

I can think of no way to do this with PatternTest. (Because as stated above each element of the sequence is tested independently.)

There is one rather obscure (at least to me) yet very important use of Condition that extends this generality.

lhs := Module[{vars}, rhs /; test] allows local variables to be shared between test and rhs. You can use the same construction with Block and With.

This is quite unusual in Mathematica's patterns and assignments. It allows execution of code as part of the definition, then testing by a condition based on the result. If the condition fails, the pattern matcher then moves on to search for other matches. The evaluation that occurred can produce side effects but otherwise Mathematica behaves as though the entire pattern (lhs := rhs assignment) did not match.

One elegant use of this functionality is the Trott-Strzebonski method for In-Place Evaluation.


Leonid wrote, and encouraged me to include here:

One other thing I want to mention is that with PatternTest, it is easier to inadvertently leak evaluation, while in Condition avoiding that is usually just a matter of inserting Unevaluated in a proper place. I discussed this topic to some extent here

Finally, there are some syntactic differences which are good to keep in mind, for example precedence-related issues like this one.


Rojo stated:

Another consequence of this shows when you want to store a pattern in a variable, or inject it with a With. ... Can't do that with Condition unless you want all the instances of the pattern in each definition to be the same.

As a rather contrived counter-example one can use Unique symbols in a pattern constructor:

pat[] := Pattern[#, _] /; # > 4 & @ Unique[]

f[a : pat[], b : pat[]] := {a, b}

f[5, 6]

{5, 6}

Of course it is better to use PatternTest for this, but I think it is useful to show that it can be done.

deleted 38 characters in body
Source Link
Mr.Wizard
  • 273.1k
  • 34
  • 595
  • 1.4k
Loading
added 642 characters in body
Source Link
Mr.Wizard
  • 273.1k
  • 34
  • 595
  • 1.4k
Loading
added 374 characters in body
Source Link
Mr.Wizard
  • 273.1k
  • 34
  • 595
  • 1.4k
Loading
added 44 characters in body
Source Link
Mr.Wizard
  • 273.1k
  • 34
  • 595
  • 1.4k
Loading
Source Link
Mr.Wizard
  • 273.1k
  • 34
  • 595
  • 1.4k
Loading