1

c++ boost 绑定库和clojure 的部分函数非常相似。例如:

int x = 8;
bind(std::less<int>(), _1, 9)(x);   // x < 9

这类似于 clojure 的偏函数:

((partial > 9) 8)

不同之处在于partial只允许绑定前 n 个参数,而boost::bind允许使用占位符指示哪些参数是绑定的,哪些是未绑定的。所以boost::bind实际上更通用和有用:

bind(f, _2, _1)(x, y);                 // f(y, x)

bind(g, _1, 9, _1)(x);                 // g(x, 9, x) 

我想知道boost::bind在 clojure(或 clojure-contrib)中是否有类似的东西?为什么 partial 没有按原样写得更通用(和有用)boost::bind

4

3 回答 3

7

这是 Clojure 的一个相当常见的问题,更经常地用线程宏 -> 和 ->> 来表达,为什么它们也不允许任意占位符。

在我看来,给出的理由也适用于这里:惯用的 Clojure 函数通常会分解成使它们的第一个或最后一个参数分开提供的函数,而不是混合提供的函数。

换句话说,开发人员通常会尝试编写函数,以便它们适合 ->、->> 和/或部分函数。

鉴于匿名函数的读取器宏,在需要时创建占位符版本相当容易,用于不太惯用的情况:

#(f %2 %1) ;; bind(f, _2, _1)
#(g % 9 %) ;; bind(g, _1, 9, _1)
于 2012-06-30T18:48:01.153 回答
0

就像肖恩说的,partial解决了一个更具体的问题,一般来说,lambdas 是惯用的解决方案。也就是说,如果你很绝望,你总是可以自己动手bind

(defmacro bind
  [bound-function & args]
  (let [; helper function to parse actual argument symbols
        get-symbols (fn [s] (map second s)),
        ; help function to get the placeholder arguments
        get-placeholders (fn [s] (filter first s))
        ; collection of arguments and whether they're placeholders
        bound-args (map (fn [arg]
                        (if (= arg '_)
                          ; for placeholders, generate a new symbol
                          [true (gensym)]
                          ; otherwise, use the provided argument as-is
                          [false arg]))
                      args)]
    `(fn [~@(get-symbols (get-placeholders bound-args))]
       (~bound-function ~@(get-symbols bound-args)))))

它的用途如下:

((bind > 9 _) 8) ; true
((bind > _ _) 9 8 ) ; true
于 2012-06-30T19:45:28.393 回答
0

Swiss Arrows库允许各种其他参数线程/绑定方案。但是,其中有很多选项可以优化函数的参数以最好地使用 -> 和 ->> 宏是首选解决方案,如果不可能,请使用匿名函数作为最简单的通用解决方案。

于 2012-07-02T09:27:55.017 回答