- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
next_int() ->
receive {next_int, N} ->
self() ! {next_int, N + 1},
N
after 0 ->
self() ! {next_int, 0},
0
end.
...
[{A, next_int()}|| A <- SomeList]
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+131
next_int() ->
receive {next_int, N} ->
self() ! {next_int, N + 1},
N
after 0 ->
self() ! {next_int, 0},
0
end.
...
[{A, next_int()}|| A <- SomeList]
Простейший способ пронумеровать элементы списка эрланге. Найдено в продакшне, ошибки сохранены.
> чистота
За два прохода.
За один проход, но без хвостовой рекурсии.
Вобщем, хорошего способа по-настоящему чет не наблюдается.
http://ideone.com/1crYjm
Ну мой первый вариант тоже с реверсом тогда такой же.
А вообще, я тут подумал, без частично инстанциированых типов данных (альтернатива присваиванию), или нарушения всех трех принципов субструктурной системы типов (обмен, послабление и упрощение) невозможно генерировать список в направлении от начала к концу. Я думаю, что если напрячься, то это како-то формально можно выразить.
> невозможно генерировать список в направлении от начала к концу
Вроде бы. Не от хорошей же жизни в эрланге всё через хвостовую рекурсию и lists:reverse() пишут.
> формально можно выразить
Ну совсем не формально, но как-то так: мы можем прицепить элемент в начало списка (тем самым строя его с конца); мы можем добавить элемент в конец, скопировав весь список (медленно); мы можем забуферизовать элементы на стеке (не хвостовая рекурсия) и мы можем забуферизовать их в списке (хвостовая рекурсия + reverse). Вроде бы других вариантов тупо нет.
Он же мне на почту приходит :)
Вернее они есть, но они сводятся к буферизации элементов в том или ином виде.
Всё печально. lists:reverse/1 неизбежен.
P.S. Радует только то, что джва прохода это всё еще O(n), просто с большей константой, и то, что lists:reverse/1 достаточно шустрый, чтобы не увеличить эту константу вдвое.
Кстати, а foldr в эрланге поди сначала переворачивает список, а потом отдаёт его foldl'у?
В теории можно сделать на сях - никто не увидит узлы пока генератор не вернул результат, поэтому можно внаглую добавлять новые в конец. В реализации map'а можно поступить аналогично.
P.S. Но это может нарушить временные характеристики - емнип, тред нельзя прервать, пока он исполняет bif.
>Production
ЩИТО