Comments 20
for (var j = 0; j < data[i].temperatures.length; j++) {
totalTemperature += data[i].temperatures[j];
}
Неужели так ещё пишет кто-либо, закончивший школу?
Если быть честным, то я не понял, как коррелируют между собой
и хотя бы даже
а так же использование рекурсии вместо цикла (стек не бесконечный!), возврат функции из функции без использования прототипов (поправьте меня знатоки JS, если я неправ, у меня сильное подозрение, что функция getItem будет возвращать новый объект функции на каждом вызове).
В общем лично у меня сложилось такое впечатление, что это еще одна крайность, как и ООП головного мозга, когда за точное следование парадигме приходится платить!
для своих самых требовательных к производительности компонентов
и хотя бы даже
при функциональном подходе данные должны быть неизменны… создаёте новый массив с новыми значениями вместо изменения старого массива
а так же использование рекурсии вместо цикла (стек не бесконечный!), возврат функции из функции без использования прототипов (поправьте меня знатоки JS, если я неправ, у меня сильное подозрение, что функция getItem будет возвращать новый объект функции на каждом вызове).
В общем лично у меня сложилось такое впечатление, что это еще одна крайность, как и ООП головного мозга, когда за точное следование парадигме приходится платить!
Большинство компиляторов функциональных языков разворачивают хвостовую рекурсию в цикл
Вот только не JavaScript, пока что.
Даже не пока, а по стандарту.
TCO трудно совместима с полем arguments у функции-объекта, которое должно ссылаться на текущий инстанс аргументов.
TCO трудно совместима с полем arguments у функции-объекта, которое должно ссылаться на текущий инстанс аргументов.
А не могли бы вы развернуть мысль? Я не очень понимаю, как поле arguments мешает tco.
function f1(a) { f2() }
function f2() {
console.print(f1.arguments)
}
Если компилятор делает TCO, то когда работает f2 вызванная из f1 фрейм стека f1 должет уже быть разрушен, а f1.arguments на него ссылается.
Сохранять f1.arguments без связи с фреймом тоже нельзя. Во первых не понятно, когда его можно разрушить, во вторых одновременно могут быть несколько фреймов f1 (если она будет рекурсивно вызываться) и f1.arguments должен перескакивать на старый при каждом завершении f1.
Автор сказал ведь что жс не функциональный язык и использовал его он лишь чтобы показать как все делается в функциональных ЯП.
Благодаря иммутабельности и еще некоторым фишкам на функциональных языках гораздо проще писать параллельный код.
Благодаря иммутабельности и еще некоторым фишкам на функциональных языках гораздо проще писать параллельный код.
Корреляция между неизменяемым состоянием и производительностью очень проста: код, не хранящий состояние, легко можно распараллелить, что очевидно может решить проблемы производительности. В случае работы только на одном ядре процессора это, конечно, ничего не ускорит.
Про рекурсию и конечность стека в статье говорится, как и про tail call optimization, которая при определенных условиях позволяет конечностью стека пренебречь.
getItem будет возвращать новую функцию каждый раз, когда она вызвана, да. Но вызывается в примере она только один раз, для того чтоб вернуть одну функцию, возвращающую значение ключа «temperature».
Про рекурсию и конечность стека в статье говорится, как и про tail call optimization, которая при определенных условиях позволяет конечностью стека пренебречь.
getItem будет возвращать новую функцию каждый раз, когда она вызвана, да. Но вызывается в примере она только один раз, для того чтоб вернуть одну функцию, возвращающую значение ключа «temperature».
Самое забавное, что оптимизация хвостовой рекурсии как раз и работает за счёт отказа от неизменяемости состояния)
Так что у вас взаимоисключающие параграфы.
Так что у вас взаимоисключающие параграфы.
Интересно, а как вы связали эти мои два утверждения? Если я скажу, что зимой холодно, а в Африке тепло — вы тоже это во взаимоисключающие параграфы запишете?
Совсем не обязательно, если стек вызовов к состоянию не относить.
Можно отказаться от выделенного непрерывного стека и размещать фреймы вызовов в куче. При хвостовом вызове создается новый фрейм, а на старый теряется ссылка и его подбирает GC.
Такой подход, кроме простоты TCO, еще дает эффективные нити (был проект Stackless Python). И позволяет эффективно реализовать call-with-current-continuation, которого в js, с его любовью к ассинхронным API с каллбеками, очень не хватает.
Можно отказаться от выделенного непрерывного стека и размещать фреймы вызовов в куче. При хвостовом вызове создается новый фрейм, а на старый теряется ссылка и его подбирает GC.
Такой подход, кроме простоты TCO, еще дает эффективные нити (был проект Stackless Python). И позволяет эффективно реализовать call-with-current-continuation, которого в js, с его любовью к ассинхронным API с каллбеками, очень не хватает.
В компилируемых языках достаточно хорошо совместимо. Компилятор все равно на каждое присваивание создает новую переменную в промежуточном коде, а потом уже распределяет их по регистрам/памяти с учетом времени жизни. С иммутабельными структурами данных все несколько хуже. Некоторые алгоритмы работают на них медленнее. Но за то иммутабельность позволяет разделять (share) данные между несколькими структурами — например при добавлении в список элемента старый список копировать не приходится.
А хвостовые вызовы многие компиляторы хорошо умеют оптимизировать. На gcc у меня они компилировались даже эффективнее, чем эквивалентный список.
Со временем это может и в джаваскрипт проникнуть, привыкать надо уже сейчас :-).
А хвостовые вызовы многие компиляторы хорошо умеют оптимизировать. На gcc у меня они компилировались даже эффективнее, чем эквивалентный список.
Со временем это может и в джаваскрипт проникнуть, привыкать надо уже сейчас :-).
Благодарю за перевод. Первая часть статьи вполне доступно объяснила мне функциональный подход. Теперь можно двигаться дальше в изучении!
Всё же JS — прототипный язык, чтобы рассказать о функциональном программировании лучше использовать Scheme.
http://web.mit.edu/alexmv/6.S184/sicp.pdf
http://newstar.rinet.ru/~goga/sicp/sicp.pdf
http://web.mit.edu/alexmv/6.S184/sicp.pdf
http://newstar.rinet.ru/~goga/sicp/sicp.pdf
www.youtube.com/watch?v=m3svKOdZijA — вот годный ролик на схожую тему
Рекурсия делает код более удобочитаемым
Далеко не всегда. Порой проще в цикле разобраться, чем проследить что за параметры придут в новом рекурсивном вызове.
Sign up to leave a comment.
[Перевод] Не стоит бояться функционального программирования