5
$\begingroup$

I was looking at this Q&A about using pattern test (pattern_?test) vs pattern condition (pattern_/;cond) and came across this example where using condition was the only possible way to restrict the function parameters (function definition added by me):

Clear[fCond]
fCond[x__ /; Plus[x] == 7] := {x}^2
fCond[1, 2, 4]
(* {1, 4, 16} *)

I know that, aside from the built-in tests in MMA (IntegerQ, NumericQ, eg), one can write custom pattern tests using pure functions [2]:

test pure function

Hence, I was trying to be clever by using tests with sequence pattern (__) coupled with sequence argument for pure function (##). However, this did not work when plugging in values for the parameter/pattern.

Clear[fTest]
fTest[x__?(Plus[##] == 7 &)] := {x}^2
fTest[1, 2, 4]
(* fTest[1, 2, 4] *)

, even though the pure function test alone does work with the plugged in sequence

Plus[##] == 7 &[1, 2, 4]
(* True *)

Why doesn't pattern test work via this method? If so, is there any other way to do pattern test as opposed to pattern condition in this case?

[2]: Ruskeepaa's Mathematica Navigator 2009 p.498

$\endgroup$
5
  • 3
    $\begingroup$ Because in case of __?test the test is applied to each argument, not to the sequence as a whole. Try fTest[7, 7, 7]. I have learned it from your previous question btw :) $\endgroup$
    – Kuba
    Commented Jul 6, 2014 at 9:47
  • 1
    $\begingroup$ Your question contains so much extraneous material that I find it is hard to determine what you are really asking. In particular, in most cases we don't need images of your notebook cells. You can include evaluation results, except for graphics, using normal markdown formatting. $\endgroup$
    – m_goldberg
    Commented Jul 6, 2014 at 15:00
  • 2
    $\begingroup$ 3rd line in the Details section of PatternTest: In a form such as __?test, every element in the sequence matched by must yield True when test is applied. $\endgroup$ Commented Jul 6, 2014 at 21:28
  • $\begingroup$ Thanks for your suggestion @m_goldberg. I cleaned up my question per your recommendations. $\endgroup$ Commented Jul 9, 2014 at 18:52
  • $\begingroup$ Thanks Kuba and Sjoerd C. de Vries! I wish I could accept both of your comments as answers. $\endgroup$ Commented Jul 9, 2014 at 19:48

1 Answer 1

5
$\begingroup$

My apologies to those who closed this question for my unilaterally reopening it, but there is a nontrivial aspect to this question that I wish to address, and it would not nicely fit in comments. (I am not making an exception for myself; when someone has such an answer he wishs to give to a closed question I nearly always reopen it for him to do so.)


While I stated before that: "I can think of no way to do this with PatternTest" was not speaking rigorously and generally, but rather one-to-one substitution of methods. One can apply PatternTest to a larger expression, e.g. the entire left-hand-side, as I did for your prior question. If handling the entire LHS one must exercise care to prevent infinite recursion. Here is an example of how that may be done:

SetAttributes[sumsTo7, HoldFirst]
sumsTo7[_[s__]] := +s == 7

f[x__]?sumsTo7 := {x}

Now:

f[1, 2]
f[3, 4]
f[1, 2]

{3, 4}

It is possible to do this with an anonymous Function as well but it becomes rather baroque:

g[x__]?(Function[Null, Plus @@ Unevaluated[#] == 7, HoldAll]) := {x}

g[1, 2, 3]
g[-3, 10]
g[1, 2, 3]

{-3, 10}
$\endgroup$
1
  • $\begingroup$ Thanks @Mr.Wizard. The +s looks rather neat! $\endgroup$ Commented Jul 9, 2014 at 18:54

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.