5

I'm trying to get pcase to match against a let-bound variable. However, I can't seem to get pcase to recognize the variable correctly.

See this minimal example:

(let ((a 1)) (pcase 2 (a 7)))  => 7    ;; as predicted by the docs
(let ((a 2)) (pcase 2 (`a 7))) => nil  ;; ???

How can I get pcase to return 7 iff a = 2?

(An alternative to pcase with similar features would also suffice.)

phils
  • 48,657
  • 3
  • 76
  • 115
PythonNut
  • 10,243
  • 2
  • 29
  • 75
  • Maybe [this](http://www.newartisans.com/2016/01/pattern-matching-with-pcase/) might help? – ReneFroger Jan 29 '16 at 18:17
  • @ReneFroger, odd, I assumed that a `(pred ...)` would work (although it would be clumsy, but even `(let ((a 2)) (pcase 2 (\`(pred (lambda (x) (= x a))) 7)))` doesn't seem to work. – PythonNut Jan 29 '16 at 18:28
  • How about `(let ((a 2)) (pcase 2 ((pred (equal a)) 7)))`? – Constantine Jan 29 '16 at 18:31
  • @Constantine ah. I was under the delusion that everything needed to be backquoted after reading the docs. Your example does work. Assuming there's no more elegant way to do it, I'll accept it as an answer. – PythonNut Jan 29 '16 at 18:33
  • By the way, would something like `(let ((a 2)) (pcase a (1 5) (2 7) (3 11)))` work for you? This would evaluate to 7 when `a` is 2, to 5 when `a` is 1, etc. Is there a reason to use `(pcase constant ...)` instead of `(pcase variable ...)` if you want to match `variable` against `constant`? – Constantine Jan 29 '16 at 19:48
  • 1
    @Constantine no, this is just a minimal example. In actuality, they're both variables. I just used a constant as the casing arg because `pcase` doesn't seem to care. – PythonNut Jan 29 '16 at 19:49
  • `(let ((a 2)) (cl-case a (2 7)))` – Drew Jan 29 '16 at 22:37
  • @Drew I really am branching a single variable among multiple other variables, so I don't think that will work. – PythonNut Jan 29 '16 at 23:08

2 Answers2

7

Here's one way to do it:

(let ((a 2)) (pcase 2 ((pred (equal a)) 7)))

This snippet uses the fact that (rephrasing (describe-function 'pcase)) a predicate may have the form(FUN ARG1 .. ARGN) in which case it gets called with an N+1'th argument which is the value being matched.

Constantine
  • 9,072
  • 1
  • 34
  • 49
3

An alternative to pcase with similar features would also suffice

(let ((a 2))
  (cond ((eq a 2)
         7)))
;; => 7

This isn't a joke - everything that can be done with pcase can also be done with a combination of let and cond.

And it think it should be - gratuitous branch-introducing macros aren't helping anyone to either code faster or maintain easier. They're introducing another language you have to learn, on top of Elisp.

abo-abo
  • 13,943
  • 1
  • 29
  • 43
  • 1
    Yes, and I do usually use `cond`. Although sometimes `pcase` can be very handy and more clear than a straight `cond` (esp. when it comes to destructuring, which I'm a big fan of.) – PythonNut Jan 29 '16 at 23:09