9
$\begingroup$

Why does Cases[] output an element only in the first of the following lines?

Cases[{1, a -> 2 b}, HoldPattern[a -> 2 b]]
(*{a->2b}*)
Cases[{1, a -> 1/2 b}, HoldPattern[a -> 1/2 b]] 
(*{}*)
Cases[{1, a -> π b}, HoldPattern[a -> π b]] 
(*{}*)
Cases[{1, a -> c b}, HoldPattern[a -> c b]] 
(*{}*)
$\endgroup$
  • 3
    $\begingroup$ compare FullForm@HoldPattern[a -> 1/2 b] and FullForm@{1, a -> 1/2 b}, the rest is about reordering. $\endgroup$ – Kuba Aug 23 '18 at 8:38
  • $\begingroup$ Huh, that was a nasty one! $\endgroup$ – Henrik Schumacher Aug 23 '18 at 8:58
  • 2
    $\begingroup$ Use PatternSequence in place of HoldPattern $\endgroup$ – kglr Aug 23 '18 at 8:59
  • $\begingroup$ @kglr I think that is worth an answer and an explanation. (I'm personally interested.) $\endgroup$ – Henrik Schumacher Aug 23 '18 at 9:01
  • 1
    $\begingroup$ See also this: mathematica.stackexchange.com/a/73020/5478 $\endgroup$ – Kuba Aug 23 '18 at 9:12
8
$\begingroup$

As an alternative to HoldPattern[Evaluate[...] you can use PatternSequence which evaluates its argument:

{Cases[{1, a -> 2 b}, PatternSequence[a -> 2 b]],
 Cases[{1, a -> 1/2 b}, PatternSequence[a -> 1/2 b]],
 Cases[{1, a -> π b}, PatternSequence[a -> π b]],
 Cases[{1, a -> c b}, PatternSequence[a -> c b]]}

{{a -> 2 b}, {a -> b/2}, {a -> b π}, {a -> b c}}

Alternatively, give the pattern a name:

{Cases[{1, a -> 2 b}, p : (a -> 2 b)],
 Cases[{1, a -> 1/2 b}, p : (a -> 1/2 b)],
 Cases[{1, a -> π b}, p : (a -> π b)],
 Cases[{1, a -> c b}, p : (a -> c b)]}

{{a -> 2 b}, {a -> b/2}, {a -> b π}, {a -> b c}}

$\endgroup$
5
$\begingroup$

Thanks to Kuba's comment now I see: HoldPattern prevents the evaluation of its argument, so Cases don't match the element in the list a->b/2 that is

Times[Rational[1, 2], b]

with the unevaluated pattern

Times[b, Power[2, -1]]

Evaluate the argument of HoldPattern solves the problem:

Cases[{1, a -> b/2}, HoldPattern[Evaluate[a -> b/2]]]
(*{a -> b/2}*)

Thanks Kuba!

$\endgroup$
  • $\begingroup$ You can define myHoldPattern[x___] = HoldPattern[x]; and use in place of HoldPattern to reduce clutter. Since myHoldPattern does not hold its argument, unlike the bona fide HoldPattern, the evaluation will have happened by the time x is wrapped into HoldPattern for matching. $\endgroup$ – kkm Aug 23 '18 at 9:19
2
$\begingroup$

Here is another way by using Verbatim. Maybe it feels a bit less hacky.

{
 Cases[{1, a -> 2 b}, Verbatim[a -> 2 b]],
 Cases[{1, a -> 1/2 b}, Verbatim[a -> 1/2 b]],
 Cases[{1, a -> π b}, Verbatim[a -> π b]],
 Cases[{1, a -> c b}, Verbatim[a -> c b]]
 }

{{a -> 2 b}, {a -> b/2}, {a -> b π}, {a -> b c}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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