все время пытаюсь пихать странные оптимизации.
Например у меня есть мапа, и мне надо пробежаться по ее элементам, какие-то из них надо поменять, а какие-то удалить.
Ну я думаю: чего два раза бегать по мапе, если можно за один раз все сделать? И начинаются всякие толстые reduce, упрощенно
Enum.reduce(map, map, fn {k, v}, map ->
case k do
{1, d} -> Map.put(map, k, v + d)
{2, _} -> Map.delete(map, k)
end
end)
В более сложных случаях все превращается в лютое нечитаемое говно.
Напрашиватеся другой вариант:
map
|> Enum.map(fn
{{1, d} = k, v} -> {k, v + d}
e -> e
end)
|> Enum.filter(&match?({2, _}, &1))
|> Enum.into(%{})
Он куда более понятен, но тут бегаем фактически три раза. В ленивом хацкеле бегалось бы один раз, но тут наверняка три раза будет.
Но с другой стороны и хер бы с ним, мапы небольшие, может сотня-другая пар максимально.
Что скажете?
Я думаю можно поискать в сторону кложурных трансдьюсеров https://github.com/garyposter/elixir-transducer
First, make it correct. Then, make it beautiful. Then, if you need to, make it performant. Because 9 times out of 10, making it beautiful also makes it performant enough.
Лучше просто использовать Stream, который делает абсолютно всё то же самое, только без DSL
Интересная штука. Спасибо!
Репозиторий покрыт пылью, но там реализация очень маленькая и интересна само направление мысли.
Пиши так, чтобы было быстро писать и читаемо другим
вообще надо было сначала filter, а потом уже map, и это запросто может быть быстрее редьюса потому что эрланг любит списки
Да фиг с другими, я один пишу. И сам с трудом вникаю через неделю :D
А какая разница? Типа после фильтра список может стать короче? :)
Есть же Stream
Он тормозной
А ты куда-то спешишь?
Нет, но зачем Stream, когда есть Enum?
Если нужен fusion конвейра, то это как раз Stream, но для "маленьких" объемов он не эффективен, да.
Обсуждают сегодня