【问题标题】:Generalized Threading Macro in ClojureClojure 中的广义线程宏
【发布时间】:2012-04-21 13:00:38
【问题描述】:

注意:这与并发无关。这是关于线程宏的。

我知道-> 将对象放在第二个位置,->> 将参数放在最后一个位置。

现在,我很好奇,就像 #( ... % ) 用于函数的简写符号一样,是否有线程简写符号可以让我将参数放置在 任意 位置? p>

我们的目标是不再有一个固定的位置让线程通过......我可以编写任意形式,并在特殊位置插入 %%,而 %% 是插入线程的位置。

谢谢!

【问题讨论】:

  • 感谢您的提问。多年来我一直想问这个问题。有时我必须使用 (#(func-adaptor arg1 % arg2)) 来获得我想要的效果 -> 或 ->>。

标签: macros clojure


【解决方案1】:

Swiss Arrows 库中的“钻石棒”可以满足您的要求:

(-<> 0
 (* <> 5)
 (vector 1 2 <> 3 4))
; => [1 2 0 3 4]

也就是说,这并不是你最终经常需要的东西(或者在我的 Clojure 经验中永远

【讨论】:

  • 我喜欢这些宏如何滥用 clojure 变量名的灵活性
  • 更好的是,从 1.5 版开始,Clojure 提供了 as-&gt;,如 another answer 中所述。
  • 我经常使用as-&gt;,但我喜欢钻石棒的简洁和视觉清晰度。通常在同一线程中使用具有不同数量的常用函数(例如 mapassoc)时发生。
【解决方案2】:

有一个提供此功能的库,但我忘记了在哪里。它可能在已弃用的 clojure-contrib 中。这是-$&gt; 宏。

但是您可以从 clojure 的核心 -> macro 派生出一个来制作您正在寻找的那个:

(defmacro -$>
    ([x] x)
    ([x form] (if (seq? form)
                (with-meta (map #(if (= %1 '$) x %1) form) (meta form))
                (list form x)))
    ([x form & more] `(-$> (-$> ~x ~form) ~@more)))

并用$表示插入点:

user=> (-$> 2 str (identity $) (println $))
2
nil

从技术上讲,您可以在一种形式中使用多个 $。但是这种实现方式存在多次扩展同一个表单的问题(以换取简单性)。

【讨论】:

    【解决方案3】:

    万一其他人遇到这种情况,提供的宏存在是有原因的,但任意放置的宏不存在:后者会导致糟糕的 API 设计。

    -&gt; 宏将参数放在第一个位置。这对应于对某些主题参数起作用的函数,例如,conjassoc

    -&gt;&gt; 宏将参数放在最后一个位置。这对应于对序列起作用的函数,例如,mapreduce

    精心设计您的 API,您将不太可能需要这样的宏。

    【讨论】:

    • 有理有据,亚历克斯。尽管有时您需要通过未设计的函数来处理数据。我想人们总是可以使用 (#(f a1 % a3)) 来绕过它。
    • nth 是一个核心函数的一个很好的例子,它适用于一个集合,但不希望它作为最后一个参数,而是作为第一个参数。
    • nth 也不会像其他序列一样返回序列,因此在挖掘嵌套序列时可以很好地工作。我认为这就是它采用这种结构的原因。
    【解决方案4】:

    自 1.5 以来,Clojure 中现在有一个通用的线程宏,称为 as->

    这条推文举了一个例子来说明它是如何工作的:https://twitter.com/borkdude/status/302881431649128448

    (as-> "/tmp" x
          (java.io.File. x)
          (file-seq x)
          (filter (memfn isDirectory) x)
          (count x))
    

    第一个 'x' 绑定到 "/tmp" 并由它组成一个文件。 'x' 再次反弹到生成的文件,并通过 'file-seq' 函数等等。

    【讨论】:

    • Swiss Arrows 库很有趣,但这可能是 2014 年最好的答案,因为它自 1.5 版起内置于 Clojure。
    • 这里的 Github 代码示例:github.com/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 2020-05-29
    • 2023-02-04
    • 2019-06-09
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多