кложур уменьшить. нет начального значения, пустая коллекция

В загадке я должен завершить следующие выражения, чтобы получить истинное значение. Должна быть одна-единственная вставка, которая подходит ко всем из них.

(= 15 (reduce __ [1 2 3 4 5]))
(=  0 (reduce __ []))
(=  6 (reduce __ 1 [2 3]))

Третье выражение обеспечивает начальное значение. Следовательно, моя замена не может предоставить другую.

Эта функция прошла бы первый и третий тест на истинность:

#(+ %1 %2)

Однако второе выражение дает следующую ошибку:

clojure.lang.ArityException: неверное количество аргументов (0), переданное (...id моей функции)

Похоже, что обычно reduce вызывает данную функцию, только если длина начального значения + коллекции больше 2. Если эта длина равна 0, как в случае выше, она также вызывается — с 0 аргументами.

Кто-нибудь подскажет, как здесь быть?


person Anton Harald    schedule 11.12.2015    source источник
comment
подсказка: каков результат (+)?   -  person nha    schedule 11.12.2015
comment
Спасибо! конечно, проще некуда! (тем временем мое решение было таким: (fn [& more] (if (= (count more) 0) 0 (apply + more))) ха, ха)   -  person Anton Harald    schedule 11.12.2015
comment
Рад, что это помогает, вы все еще можете упростить его, намного ;) Не стесняйтесь смотреть на другие решения, если вы используете 4clojure.   -  person nha    schedule 11.12.2015
comment
Разве (+) не тай-файтер?   -  person Mark Fisher    schedule 11.12.2015
comment
я пытался ответить на свой вопрос здесь, в stackoverflow, но есть минимум 30 символов. очень жаль. без шансов с одним символом.   -  person Anton Harald    schedule 11.12.2015


Ответы (1)


Судя по комментариям, решение явно +, но, возможно, стоит рассмотреть его подробнее, чтобы понять, почему. Как оказалось, тут многое.

Во-первых, давайте посмотрим на reduce чтобы узнать, каковы требования:

(defn reduce
  "f should be a function of 2 arguments. If val is not supplied,
  returns the result of applying f to the first 2 items in coll, then
  applying f to that result and the 3rd item, etc. If coll contains no
  items, f must accept no arguments as well, and reduce returns the
  result of calling f with no arguments.  ..."
  ... 
  ([f coll]
     (if (instance? clojure.lang.IReduce coll)
       (.reduce ... coll f)
       ...))
  ([f val coll]
     (if (instance? clojure.lang.IReduceInit coll)
       (.reduce ... coll f val)
       ...)))

Это функция множественной арности, которая либо принимает функцию и коллекцию, либо функцию, начальное значение и коллекцию.

+ также функция множественной арности, которая ведет себя в зависимости от того, сколько аргументов вы передаете ей. Источник ниже (отредактированный для частей, которые нас интересуют) показывает, что сокращение удовлетворяется 0-арностью и 2-арностью.

(defn +
  "Returns the sum of nums. (+) returns 0..."
  ...
  ([] 0)
  ...
  ([x y] (. clojure.lang.Numbers (add x y)))
  ...

Ясно, что (reduce + []) вызывает первое предложение и возвращает 0. Объясняется тест 2.

Это работает для первого теста, применяя функцию добавления к каждой паре чисел, что происходит во внутренних компонентах Java для Clojure, в тесном for цикле.

Последний тест работает точно так же, как и первый, за исключением того, что он вызывает [v val coll] реализацию сокращения. Это относится к немного другому внутренняя функция, но с тем же эффектом.

Примечания

[1]: IFn — это Интерфейс Java для функций clojure

person munk    schedule 26.12.2015