Как стать автором
Обновить

Комментарии 32

Здесь мы просто извлекли анонимную встроенную стрелочную функцию, определённую до этого, и превратили в отдельную именованную.

Это бред. Не выдумывайте свои определения

НЛО прилетело и опубликовало эту надпись здесь
А подскажите, какое бредовое определение выдумал автор оригинального поста?

extract the anonymous in-line arrow function we defined above and turn it into a separate named function
Под «встроенными» в русском языке понимаются отнюдь не «инлайновые».
«Встроенная» никак не тянет на определение. Я согласен, впрочем, что обратный перевод скорее превращается в embedded.
Вопрос на засыпку — а как перевести «inline» на русский язык?
Я думаю в данном контексте вполне уместно было бы перевести как анонимная однострочная стрелочная ф-ция. По крайней мере такие определения встречаются довольно часто. Я не переводчик, но лично мне так было бы понятней.

Некоторое не переводится, например "инлайн стили" уже устоялись, было бы странно переводить как "встроенные стили". Если в контексте статьи и конкретной фарзы, то перевод слова инлайн избыточен, поэтому достаточно было написать "стрелочаня функция".

последний пример с редюсом какой-то надуманный, там вполне хватило-бы .join('')
на мой вкус редюс лучше подходит для преобразования массивов в объект

var dict = ['Cat', 'Dog', 'Birg'].reduce((result, an, id) => { result[an] = id; return result;});

Только ваш пример работать не будет, вы забыли инициализировать начальное значение.


var dict = ['Cat', 'Dog', 'Birg'].reduce((result, an, id) => { result[an] = id; return result;}, {});
Каюсь, поспешил и забыл элементарно проверить ( в своем глазу бревна не увидел :)
var dict = {} ; [ 'Cat', 'Dog', 'Birg' ].forEach( ( an , id )=> dict[ an ] = id )
Не забывайте, что метод filter наверняка будет работать чуть медленнее, чем цикл for, пока браузеры и JS-движки не будут оптимизированы под новые методы работы с массивами.


Парой абзацев ниже

Не бойтесь начать использовать фильтрацию. В ES5 эта функциональность нативна и поддерживается почти везде.


АААААА, как быть то? Получается, не бояться использовать чтобы тормозило?
Консоль Google Chrome выдает «Array.filter (native)»
Полагаю хоть немного, но все же оптимизированы.
Хотя можно и проверить какой способ и насколько быстрее.
В IE9+ — уже не тормозит. Не говоря уж про другие браузеры.

А разве в основе filter/map/reduce не лежат простые циклы?

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

Не совсем понятно в чем суть оптимизации если результат все равно будет O(n). Разве сейчас это уже не нативные методы? Во всяком случае в chrome Array.prototype.filter очень похож на нативный.

Нативный метод может быть реализован на javascript или еще хуже — смеси c++ и javascript, сейчас почти все методы массива не оптимизированы на типизированных массивах. O(n) тоже бывает разным.

Мне кажется это уже попахивает фанатизмом, конечно O(n) бывает разным, на разных поколениях машин. Давайте теперь не будем пользоваться умножением и делением, особенно внутри циклов, ведь это очень накладно. Если вы пишете компилятор C++ на JavaScript, то наверное вы что то делаете не так, а для повседневного использования, отрисовки списков или обработки асинхронных сообщений на стороне сервера вам должно за глаза хватить всех операций стоимостью O(n). Про корень зла не забыли?

Я про внутреннюю реализацию в браузере, сейчас в v8 эти методы переводят на с++ и они будут инлайнится компилятором чтоб убрать расходы на переключение между с++ и js и повысить производительность. Про O(n) — сравните 100 n и n ** 2 при небольших n — или n и 10000 n, все имеет значение, для этого и используют комбинированные алгоритмы. У меня повседневное использование это счет и отрисовка графики, компилятор — нет, хотя не вижу в этом ничего дурного, но кодеки писали, не сказал бы, что мы что-то делаем не так.

Неужели в счете и отрисовке вы используете filter/map/reduce? Хотя мы уходим немного в сторону. Вот смотрите кусочек Linq#Where кода аналога filter под Mono:


        static IEnumerable<TSource> CreateWhereIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            foreach (TSource element in source)
                if (predicate (element))
                    yield return element;
        }

Там есть еще один такой же для массивов с циклом for. Filter версия должна быть очень схожа. Я не вижу разницы буть то написано даже на js или прямиком на c++. Метод прост как трусы за рубль двадцать. Вот что здесь оптимизировать, какие тут мега сложные проверки, которые нужно устранить?

А почему я их не должен использовать? Я и Foldable монады использую с их методом reduce там где это помогает читабельности. Оптимизация — это уже второй вопрос, где нужно можно и через цикл переписать, но обычно до этого не доходит, тем более на этом много не выиграешь.

В моно у вас компилятор перед выполнением все проверки сделает и выдаст вам идеальный машинный код, а в жс это все будет делать JIT ему прийдется многое угадывать и про ваш элемент и про ваш предикат. А если код который будет выполняться в компиляторе написан на смеси жс и с++ (да v8, это как раз компилятор с++ на жс и с++) то у вас будет теряться время на переход, так что не все так просто.
Ну хотя метод и прост на первый взгляд, под использованием foreach (если это C#) спрятаны вызовы GetEnumerator, Next, Current — которые могут быть переопределены и сделаны вообще специально для того чтобы помогать вам разбираться с коллизиями в духе

var a = ['a']
a.filter(i => { a.push('b'); return Math.random() > 0.5 })


Трусы за рубль двадцать будут несколько проще таки. И оптимизировать тут есть что.
Я правильно понимаю что
const threeLetterAnimals = animals
.filter(exactlyThree)
.map(capitalize)
.reduce(studlyCaps);

сначала создаст отфильтрованный массив, потом ещё дополнительно два раза по нему пробежится?
Если так, то выглядит, конечно, красиво, но как то не сильно производительно.
Ясное дело, это пример, но всё равно выглядит как то не очень.

Добро пожаловать в жестокий мир. Не совсем понятно почему это не сильно производительно, сложность тут линейная O(n). Но к счастью если вас заботит раздутие конечного автомата вы всегда можете использовать трансдьюсeры

сложность тут линейная O(n)
Это не отменяет факта, что по массиву пробежимся два раза.
За трансдьюсеры спасибо, не знал про такое. Тогда да, можно красоту наводить.
оверхед самого цикла не большой потому разница между
for(const el of arr) {f(el); g(el);}

и
for(const el of arr) f(el);
for(const el of arr) g(el);

не значительна
Если массив большой, разница времени выполнения будет различаться в два раза. Если массив маленький, то не сильно страшно, конечно.
Но всё равно мне не нравится такое увеличение на пустом месте ради красоты. Наверное, опыт программирования микроконтроллеров даёт такие страшные побочные эффекты ))).
Для тежелых операций f, g разница не может быть в два раза, если операции очень дешевые, то оверхед может быть заметен и как раз и будет давать разницу в два раза.

Как правило, если проект большой, лучше писать красивее и понятнее, а уже потом думать о скорости. Часто узкие места появляются совсем не там где их ждешь.
При таких условиях, да, согласен.
Просто в жс быстрый код — это обычно уродский код, а его не так просто поддерживать. Понятно, что стоит выделять критические места типа работы с многомерными массивами в библиотеки и их уже максимально оптимизировать. Но проект лучше держать в читабельном виде максимально долго.
Сколько можно уже мусолить эту тройку {map, filter, reduce} (первые 2 легко выводятся из свертки(катаморфизма) reduce)?
Зарегистрируйтесь на Хабре , чтобы оставить комментарий