Где таскание? В пользовательском коде? Этого можно избежать, и я сказал как. В коде функции? Два места — проверка (которая будет и в итеративном коде) и рекурсивный вызов (в итеративном подходе у вас будет инкремент счетчика ну или хотя бы декларация цикла).
О ужас, один лишний параметр. У вас этот «лишний» — счетчик. Там где напрашивается рекурсия, рекурсивный код будет компактнее (ваши же примеры это подтверждают) и, скорее всего, в нем будет меньше сущностей. Насчет этого я, надеюсь, вы согласитесь.
Позвольте тогда поинтересоваться, что в вашем понимании тогда «торчание ушей реализации» и как они не будут торчать в итеративной реализации.
Если вы говорите про то, что у функции будет лишний параметр — есть параметры по умолчанию или можно сделать обертку, если вас это так коробит в эстетическом плане.
Насчет максимальной глубины — да, зависит. А вы количество циклов ( размер стека) тоже ограничиваете в зависимости от сложности конкретного участка кода? Или выбираете какое-то разумное ограничение, которое не должно зависеть от реализации?
Не очень понял, для кого рассчитана эта статья. На мой взгляд, новичок ничего не поймет (хотя бы потому, что нет четкого определения).
Для знакомого с рекурсией — зачем пример про обход дерева и числа фибонначи? Это же элементарно.
Про хвостовую рекурсию — ни слова
Множественная рекурсия, косвенная рекурсия — тоже не слышал.
Основная донесенная мысль, как я понял — рекурсия вредна, т.к.
1) внезапно может закончится стек и все сломается
2) есть более оптимальные нерекурсивные алгоритмы
Использование своего стека вместо стека вызовов — замечательно, только вот он тоже конечный и тоже может внезапно кончиться. Если подразумевается контролирование глубины рекурсии, не вижу проблемы передавать параметр глубины в рекурсивный вызов и делать проверку.
Насчет оптимальности. Эту проблему решает динамическое программирование. В случае, когда разные ветки решают повторяющиеся подзадачи — разумеется, надо оптимизировать. Но это можно решить разными способами, не только переходом на нерекурсивный вариант.
Рекурсия зачастую существенно поднимает читаемость кода. Время программиста сейчас дороже, чем время процессора.
Мой пример задачи, которую муторно решать нерекурсивно — deepCopy для json, где в зависимости от типа object/array/primitive вызываются разные методы (пример косвенной и множественной рекурсии кстати).
В torrc (tor-browser_en-US/Browser/TorBrowser/Data/Tor/torrc или /etc/tor/torrc)
ExitNodes {ru}
Для нескольких стран
ExitNodes {ru},{by}
Не так уж и трудно.
Расскажите, пожалуйста, о проектах на Scala, в которых вы участвовали. И, если это возможно, какие из частей вашего курса реально соприкасаются с этими проектами и каким образом.
Вам не надо спорить о форматирование и кодстайле. Есть множество инструментов, которые последовательно освещают эти вопросы. Важно, чтобы код был корректным, понятным и поддерживаемым. Конечно, стиль и форматирование — часть этого, но вы должны дать инструментам проверить эти вещи.
В чек-листе:
Соответствует ли код вашему стилю написания кода? Обычно это относится к расположению скобок, названиям переменных и функций, длинам строк, отступам, форматированию и комментариям.
Просто на мой взгляд трудно будет назвать такую функцию чистой. Извините, я не силен в терминах монад. Я понял ваш ответ так, что вызов такой функции генерации случайного числа изменяет некое состояние (или проводит действие, эквивалентное изменению состояния). Мне кажется, что тогда можно утверждать, что функция будет иметь побочные эффекты, что делает ее грязной. Следовательно, утверждение «все функции в Хаскелле чистые» неверно.
«В языках программирования функции, которые всегда дают одинаковый результат на одинаковых аргументах и не имеют побочных эффектов, называются чистыми. В чистом функциональном языке наподобие Haskell все функции чисты.»
С этой точки зрения — в Хаскелле нет функции генерации псевдослучайного числа без аргументов? Есть. Какое-то противоречие.
Присоединюсь к комментариям — ничего нового в этой ручке не увидел. На старой работе приходилось общаться с «умными» ручками. У них у всех один большой минус — датчик находится не на конце шарика/пера, а выше минимум на полсантиметра. Соответственно точность очень хромает — при письме далеко не всегда сохраняется постоянный наклон ручки. Можно поставить точку и повращать ручку — на бумаге будет точка, в памяти — окружность.
Т.е. если я выложу на pastebin словарные пароли, предварительно добавив в каждую строку имя пользователя, то ему будут постоянно сыпаться сообщения о необходимости смены пароля?
О ужас, один лишний параметр. У вас этот «лишний» — счетчик. Там где напрашивается рекурсия, рекурсивный код будет компактнее (ваши же примеры это подтверждают) и, скорее всего, в нем будет меньше сущностей. Насчет этого я, надеюсь, вы согласитесь.
Если вы говорите про то, что у функции будет лишний параметр — есть параметры по умолчанию или можно сделать обертку, если вас это так коробит в эстетическом плане.
Насчет максимальной глубины — да, зависит. А вы количество циклов ( размер стека) тоже ограничиваете в зависимости от сложности конкретного участка кода? Или выбираете какое-то разумное ограничение, которое не должно зависеть от реализации?
Для знакомого с рекурсией — зачем пример про обход дерева и числа фибонначи? Это же элементарно.
Про хвостовую рекурсию — ни слова
Множественная рекурсия, косвенная рекурсия — тоже не слышал.
Основная донесенная мысль, как я понял — рекурсия вредна, т.к.
1) внезапно может закончится стек и все сломается
2) есть более оптимальные нерекурсивные алгоритмы
Использование своего стека вместо стека вызовов — замечательно, только вот он тоже конечный и тоже может внезапно кончиться. Если подразумевается контролирование глубины рекурсии, не вижу проблемы передавать параметр глубины в рекурсивный вызов и делать проверку.
Насчет оптимальности. Эту проблему решает динамическое программирование. В случае, когда разные ветки решают повторяющиеся подзадачи — разумеется, надо оптимизировать. Но это можно решить разными способами, не только переходом на нерекурсивный вариант.
Рекурсия зачастую существенно поднимает читаемость кода. Время программиста сейчас дороже, чем время процессора.
Мой пример задачи, которую муторно решать нерекурсивно — deepCopy для json, где в зависимости от типа object/array/primitive вызываются разные методы (пример косвенной и множественной рекурсии кстати).
ExitNodes {ru}
Для нескольких стран
ExitNodes {ru},{by}
Не так уж и трудно.
В чек-листе:
Сами себе противоречат?
С этой точки зрения — в Хаскелле нет функции генерации псевдослучайного числа без аргументов? Есть. Какое-то противоречие.
2. Случайно взламываем самого себя
3. Майним биткоины
4. Плачемся амазону
5.…
6. PROFIT!!!
Насчет определения — так никто не мешает попробовать обе комбинации. Тем более не все символы допустимы в логинах.