首页 > 解决方案 > Clojure 中的高阶 if-then-else?

问题描述

如果数据满足某些条件,我经常不得不通过函数运行我的数据。通常,函数f和标准检查器pred都被参数化为数据。if-then-else出于这个原因,我发现自己希望得到一个既不知道f也不知道的高阶pred

例如,假设我想10(range 5). 代替

(map #(if (even? %) (+ % 10) %) (range 5))

我宁愿有一个助手——让我们称之为fork——然后这样做:

(map (fork even? #(+ % 10)) (range 5))

我可以继续并实现fork为功能。它看起来像这样:

(defn fork
  ([pred thenf elsef]
   #(if (pred %) (thenf %) (elsef %)))
  ([pred thenf]
   (fork pred thenf identity)))

这可以通过优雅地组合core功能来完成吗?一些不错的链juxt//也许applysome

或者,您知道任何实现上述(或类似)的 Clojure 库吗?

标签: clojurehigher-order-functionspointfree

解决方案


正如 Alan Thompson 所提到的,cond->这是一种相当标准的方式,隐含地让“else”部分成为“返回不变的值”。但是,它并没有真正解决您成为高阶的希望。我还有另一个不喜欢的理由cond->:我认为(并争论何时cond->发明)它通过每个匹配测试而不是第一个测试是错误的。这使得它无法cond->用作cond.

如果您同意我的观点,您可以尝试1 或该系列中的其他工具之一,这是我们在1flatland.useful.fn/fix年前编写的。cond->

to-fix正是你的fork,除了它可以处理多个子句并接受常量和函数(例如,也许你想将 10 添加到其他偶数但将 0 替换为 20):

(map (to-fix zero? 20, even? #(+ % 10)) xs)

很容易复制cond->using的行为fix,但反之则不然,这就是为什么我认为这fix是更好的设计选择。


1显然,距离fix. 时光飞逝。


推荐阅读