clojure's -> (arrow) operator and optional operations

clojure, operators, syntax

Solution

You can do it with `cond->`, newly introduced in Clojure 1.5:

(cond-> x
  true        a
  (> (a x) 2) b
  true        c)

Or, better,

(-> x
  a
  (cond-> (> (a x) 2) b)
  c)

Meaning, "take `x`, thread it through `a`, take the result and thread it through `b` if `(> (a x) 2)` or else leave it unchanged, finally take what you've got and thread it through `c`".

In other words, `cond->` is like `->`, except instead of single forms to thread your expression through it takes test+form pairs, where the form is skipped if test is falsey and used for threading if test is truthy:

(cond-> x
  test-1 form-1
  test-2 form-2)

;; if test-1 is truthy and test-2 is falsey, output is as if from
(-> x test-1)

;; if it's the other way around, output is as if from
(-> x test-2)

;; if both tests are truthy:
(-> x test-1 test-2)

;; if both tests are falsey:
x

Problem

I've run in several situations where I want to do a chain of operations on an object with optional functions. "->" works great for sequences of commands on the same object (ex. (c (b (a x))) becomes (-> x a b c) ), except if some operations are optional. For example, suppose I wanted to do: ``` (c (if (> (a x) 2) (b (a x)) (a x) ) ) ``` Is there any way to do that in a clearer fashion using an operation like "->"?

Original source