2012-06-30 3 views
1

C++ boost bind library и частичная функция clojure очень похожи. Например:C++ boost :: bind vs clojure partial function

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

Это похоже на частичную функцию Clojure в:

((partial > 9) 8) 

Разница заключается в том, что partial допускает только первые п параметров для связывания, тогда как 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-вно)? И почему частичное не было написано более общим (и полезным), поскольку boost::bind есть?

+1

Почему бы просто не сделать лямбда? – kennytm

+0

тем рассуждением, зачем включать частично в язык вообще? Это просто частный случай лямбды. Я лично считаю, что частичное яснее. – Kevin

+0

Но C++ 03 не имеет лямбда. – kennytm

ответ

7

Это довольно часто задаваемый вопрос о Clojure, чаще всего выражаемый в терминах макросов с потоками -> и - >> относительно того, почему они также не допускают произвольные заполнители.

Приведенная здесь причина также применима здесь, на мой взгляд: идиоматические функции Clojure, как правило, разбиваются на те, которые предоставляют себе либо их первый, либо последний аргумент, поставляемый отдельно, а не смесь.

Другими словами, разработчики обычно пытаются выполнить функции кода, чтобы они были поддаются ->, - >> и/или частичным.

Учитывая читатель макросов для анонимных функций, это довольно легко создать версии заполнителей, когда они необходимы, для менее идиоматических ситуаций:

#(f %2 %1) ;; bind(f, _2, _1) 
#(g % 9 %) ;; bind(g, _1, 9, _1) 
+0

Это интересно, потому что я почти упомянул о потоковом макросе. То, что вы говорите, может быть правдой, но правило ломается, как только вы начинаете называть java-методы, которые неизменно не следуют этому правилу. Затем я вынужден писать менее сжатый код, чем хотелось бы, потому что макрос потоков не является таким общим, каким он может быть. Но спасибо за ответ. – Kevin

+0

Или, что более типично, что происходит, я хочу, чтобы нить arg thru 5 методов и 4 нужно было нарезать как первый arg, а пятый - значение, заимствованное как последний arg. – Kevin

+0

Это может быть не идиоматично, но я написал этот макрос некоторое время назад и нашел его полезным.Он похож на -> или - >>, но потоки на основе% маркеров. Например. (% -> 300 (/% 10) (/ 60%)) вернется 2. (defmacro% -> ([x] x) ([x форма] (если (seq? Форма) (с- meta (postwalk-replace {'% x}) (0) (list form x))) ([x form & more] '(% -> (% -> ~ x ~ form) ~ @ больше))) –

0

Как Шон сказал, partial решает более конкретную проблему и в общие, лямбды - это идиоматическое решение. Тем не менее, если вы в отчаянии, вы всегда можете свернуть свой собственный 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 [[email protected](get-symbols (get-placeholders bound-args))] 
     (~bound-function [email protected](get-symbols bound-args))))) 

Его использование заключается в следующем:

((bind > 9 _) 8) ; true 
((bind > _ _) 9 8) ; true 
+0

Заполнители должны быть пронумерованы или аргументы не могут быть переупорядочены/проигнорированы и т. Д., Но я получаю эту идею. – Kevin

0

Там в Swiss Arrows библиотека, которая позволяет для различных других параметров резьбы/связывания сценарий годов. Тем не менее, существует так много вариантов, что оптимизация параметров вашей функции для наилучшего использования макроса -> и - >> является предпочтительным решением, и если это невозможно, используйте анонимные функции в качестве простейшего общего решения.

Смежные вопросы