Как реализовать методы array.any()
и array.all()
в Coffeescript?
Как реализовать методы array.any() и array.all() в Coffeescript?
Ответ 1
На самом деле это часть Javascript 1.6 и будет одинаково работать в CoffeeScript. Вы хотите some и every.
Я не знаю, в какой среде вы находитесь, но IE < 9, похоже, не поддерживает эти методы. Их довольно легко добавить. Там фрагмент кода на тех страницах, которые показывают код совместимости, и если вы хотите, вы можете перевести их на CoffeeScript, хотя вы не должны.
Более грубый, более простой способ был бы (непроверен):
if not Array.prototype.some
Array.prototype.some = (f) -> (x for x in @ when f(x)).length > 0
if not Array.prototype.every
Array.prototype.every = (f) -> (x for x in @ when f(x)).length == @length
Но ни один из них не имеет логики короткого замыкания. Изменить. Но см. ответ Рикардо для лучшей версии.
Ответ 2
Короткозамкнутые (оптимизированные) версии:
Array.prototype.some ?= (f) ->
(return true if f x) for x in @
return false
Array.prototype.every ?= (f) ->
(return false if not f x) for x in @
return true
?=
предназначен для "экзистенциального назначения", выполняется только тогда, когда это свойство null
/undefined
.
Ответ 3
Отметьте underscore.js, который предоставляет вам методы _.any
и _.all
(aka _.some
и _.every
) который будет работать в любой крупной среде JS. Вот как они реализованы в CoffeeScript в underscore.coffee:
_.some = (obj, iterator, context) ->
iterator ||= _.identity
return obj.some iterator, context if nativeSome and obj.some is nativeSome
result = false
_.each obj, (value, index, list) ->
_.breakLoop() if (result = iterator.call(context, value, index, list))
result
_.every = (obj, iterator, context) ->
iterator ||= _.identity
return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
result = true
_.each obj, (value, index, list) ->
_.breakLoop() unless (result = result and iterator.call(context, value, index, list))
result
(Они зависят от _.each
, который представляет собой простой метод итерации, и _.breakLoop
, который просто генерирует исключение.)
Ответ 4
Я смотрел на это сегодня и решил реализовать all
как сгиб, и я полагаю, что вы могли бы сделать то же самое и для any
(но это тоже не короткое замыкание):
all = (someArray, predicate) ->
reduceAll = (left, right) ->
return left and right
return [predicate(elem) for elem in someArray].reduce(reduceAll, true)
Некороткое замыкание any
будет в основном аналогичным:
reduceAny = (left, right) ->
return left or right
[p(elem) for elem in someArray].reduce(reduceAny, false)
Я сделал all
таким образом, потому что нашел его читаемым. Кроме того, я просто сделал это как функцию свободного плавания вместо метода массива.