1

I want foo to accept two params and if the first one is :ok it should return second param, otherwise first param.

I want to do it with pattern matching like this:

(defn foo [:ok val] (val))
(defn foo [key val] (key))

But it is not supported. Can I do it the similar way (using pattern matching or some kind of)?

Max Smirnov
  • 477
  • 3
  • 10
  • Does this answer your question? [Pattern matching functions in Clojure?](https://stackoverflow.com/questions/8596980/pattern-matching-functions-in-clojure) – Martin Půda Apr 22 '23 at 03:51
  • @MartinPůda not really, because it uses conditional matching, but I want match with literal. I hope for my case there is more simple solution. – Max Smirnov Apr 22 '23 at 06:34
  • Your evaluation is conditional. The first pattern is tried before the second. – Thumbnail Aug 03 '23 at 07:49

3 Answers3

6

if the pattern is not too complex, you can achieve something close to pattern matching using multimethods:

(defmulti foo (fn [key val] key))
(defmethod foo :default [key _] key)
(defmethod foo :ok [_ val] val)
erdos
  • 3,135
  • 2
  • 16
  • 27
1

You could use [patterned "0.2.0"]

(require '[patterned.sweet :as p])
(p/defpatterned foo
    [:ok val] (val)
    [key val] (key))

(foo :ok +)
=> 0
(foo  * +)
=> 1

See the pattern project.

akond
  • 15,865
  • 4
  • 35
  • 55
0

Here is one way to do it.

(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(defn foo
  [a b]
  (if (= :ok a)
    b
    a))

(verify
  (is= (foo :ok   :something) :something)
  (is= (foo :nope :something) :nope))

If there were more than 2 cases, you may want to use a (cond ...) form.

Built using my favorite template project.

Alan Thompson
  • 29,276
  • 6
  • 41
  • 48