2013-02-09 6 views
9

Примеры Clojure Арность-перегрузки на функции, как в следующем (взято из cookbook):Clojure :: Arity перегруженных функций звонить друг другу

(defn argcount 
    ([] 0)        ; Zero arguments 
    ([x] 1)        ; One argument 
    ([ x & args] (inc (count args)))) ; List of arguments 

... использовать форму, которая не кажется позволяют функциям lower arity просто вызывать функции более высокой степени с некоторыми значениями по умолчанию (это обычная идиома в Java). Используется ли какая-то другая специальная форма?

+3

Есть два способа сделать это, и этот вопрос уже был дан ответ на StackOverflow. Обратите особое внимание на второй, более поздний ответ здесь: http://stackoverflow.com/a/8660833/152739 – Scott

+0

Кажется, все в порядке: user => (defn f ([] (f 1)) ([ x] x)) # 'пользователь/f пользователь => (f) 1 –

ответ

13

Обычно существует хороший способ выразить более высокие аргументы arity таким образом, что не нужно ссылаться на другие типы, используя функции более высокого порядка, и map/reduce. В этом случае это довольно просто:

(defn argcount 
    ([] 0) 
    ([x] 1) 
    ([x & args] 
    (reduce + 1 (map (constantly 1) args)))) 

Обратите внимание на общий вид выражения:

(reduce reducing-function arity-1-value (map mapping-function rest-of-args)) 

Вы не можете сделать все это так, но это работает на удивление большая доля мульти- функции аргумента. Он также получает advnatages лени, используя map, так что вы можете делать сумасшедшие вещи, как проход десять миллионов аргументов функции с небольшим страхом:

(apply argcount (take 10000000 (range))) 
=> 10000000 

Try, что в большинстве других языков, и ваш стек будет тост :-)

3

Ответ mikera является удивительным; Я бы добавил дополнительный метод. Если для перегруженной функции требуется значение по умолчанию, может использоваться локальная.

В приведенном ниже примере подразделение требует номеров и точности. Определенная функция перегружает точность значением по умолчанию.

(def overloaded-division 
(let [divide-with-precision 
    (fn [divisor dividend precision] 
    (with-precision precision (/ (bigdec divisor) (bigdec dividend))))] 
    (fn 
     ;lower-arity calls higher with a default precision. 
     ([divisor dividend] (divide-with-precision divisor dividend 10)) 
     ;if precision is supplied it is used. 
     ([divisor dividend precision] (divide-with-precision divisor dividend precision))) 
    ) 
) 

При вызове в нижнем арностью, по умолчанию он применяется:

user=> (overloaded-division 3 7) 
0.4285714286M 
user=> (overloaded-division 3 7 40) 
0.4285714285714285714285714285714285714286M 
Смежные вопросы