Чеж тогда все Бейсик ругали с его goto? Писали бы ответственно и проблем бы не было…
Не знаю, может там был дефицит других управляющих итерациями синтаксических конструкций… я уже с Паскаля начинал… там тоже был goto, но проблем от этого не было )
Всегда ведь можно сформулировать code convention, исходя из бизнес-требований. Бизнесов много и они разные, поэтому не уверен, что это на уровне разработчиков языка надо делать.
Просто "сайд-эффект" — это очень расплывчатое понятие. Некоторые даже нагрев процессора к ним относят :-)
С одной стороны можно считать сайд-эффектом любое действие внешнее к программе — запись в БД или в лог.
А с другой — только побочный/неожидаемый эффект от вызова функции. Когда Вы вызываете условно db.insert!(comment), то это вполне ожидаемо приведёт к запросу к БД, а вот то, что этот же код приведёт к отправке email-уведомлений, отправит нотификацию в веб-сокет, а может и ещё что-то… вот это уже нифига неочевидно и обычно имеют в виду избежание именно сайд-эффектов такого типа.
А как с этим делом в других языках, например в том же Elixir?
Если говорить о работе с разделяемой памятью, то используется модель акторов(запускается легковесный процесс, хранящий разделяемое состояние, а все остальные, чтобы повлиять на это состояние, шлют ему сообщения, которые применяются в порядке очереди). Вот тут можно почитать подробнее. Плюс недавно вышла хорошая статья на тему зачем вообще ФП в Erlang и Elixir
По-моему важно понимать, что если модели предметной области(классы, содержащие бизнес-логику), у вас не наследуют ActiveRecord::Base, то у вас нет паттерна ActiveRecord в проекте. Возможно вы используете рельсовый AR в качестве странной реализации паттерна Repository, возможно ещё как-то… но только не в качестве ActiveRecord.
При функциональном подходе обычно Virtual DOM является и входящим параметром, и результатом обработчиков. А реальный DOM скорее тем самым глобальным состоянием, которое напрямую никто не трогает.
Вероятно, сторонники ФП, говоря о нелюбви к состояниям, имеют в виду работу с ними как стиль, а не их существование вообще.
Да любим мы состояния… проблема не в состояниях, а в работе с разделяемой памятью, особенно когда имеет место конкурентный доступ.
Для этого в функциональном подходе используют STM и Actor Model
Т.е. Вы с проблемами от использования AR не сталкивались? И никаких неудобств от того, что логика предметной области находится в моделях AR не испытывали?
А причём тут религия? Вы же сами написали, что AR нигде толком не получился. Я только добавил, что он by design не может толком получиться и неизбежно будет доставлять проблемы в нетривиальных случаях.
Спорно. Всё-таки читабельность — это ответственность программиста. И выразительные средства языка ему в этом помогают.
А урезание выразительных возможностей наоборот снижает читабельность в сложных проектах. Для примера можно код крупных проектов на Go посмотреть.
После других языков самое непривычное в Ruby — это необязательность скобок (т.н. poetry mode)
Вообще вопросы синтаксиса — это очень субъективно… кто-то синтаксис Python терпеть не может из-за отсутствия end или фигурных скобок, кому-то def в Ruby не нравится. Можно от всего этого абстрагироваться для решения какой-то единичной задачи, но при выборе языков для постоянного использования всё-таки важно, чтобы синтаксис был по душе.
Что касается Django, выше уже отметили, что по большому счёту у него все те же проблемы, что и у Rails.
P.S. Если Вам нравится Python, то посмотрите ещё на Nim.
Ну, крайность, не крайность. А в принципе это глобальное состояние системы, и именно из него она восстановится после жёсткого перезапуска. Просто мы тут о другом состоянии говорим, о том которое находится в ОЗУ и доступно на протяжении процесса обработки запроса.
Например, k(x) может обращаться к БД и извлекать оттуда данные (params[:id]), h — как-то обрадабывать эти данные, например, преобразовать их в список чисел, следующая функция может возвести их в квадрат.
Ну вот, Вы сами описали как функции, одна за другой меняют состояние, которое передаётся по цепочке.
Состояние на уровне отдельной функции тоже можно рассматривать, так сказать, мгновенное состояние… но набор локальных «переменных» нас слабо волнует, интерес представляет только то состояние, которое передаётся по цепочке функций. По поводу всего остального мы просто ожидаем, что половину из этого компилятор нафиг уберёт, а остальное подчистит сборщик мусора )
Функция — просто правило, по которому элементы одного множества сопоставляются другому. О каком состоянии может быть речь?
Состояние — это один из аргументов функции, например, в той же хвостовой рекурсии при вычислении факториала начальное состояние будет = 1, а итоговое — результат. Просто Вы это называете не состоянием, а вычисляемым значением, хотя, строго говоря, вычисляемое значение — это только конечное состояние.
Когда мы говорим, что данные неизменяемые, мы не лукавим, т.к. они физически не меняются в ОЗУ, в отличии от императивных языков. Насколько я понимаю, именно это помешало распространению ФП в прошлом веке, т.к. программы работали медленнее из-за неизменяемости данных, но со временем это оптимизировали. И теперь людей больше интересует как запустить сотни потоков и не получить ни race condition от доступа к изменяемым данным, ни геммороя с блокировками.
Я предполагаю, что в данном контексте состоянием является некоторый переменный(upd.) набор данных, принадлеащий системе.
В таком определении у Вас состояние — это вся база данных + redis + ещё что-то. Слишком глобально и внешне к самому приложению.
Давайте возьмём для примера веб-приложение, оно обрабатывает входящие HTTP-запросы. Задача приложения обработать запрос и выдать HTTP-ответ. Для простоты рассмотрим один поток выполнения. Получив запрос, приложение создаёт некоторую структуру данных, описывающую запрос. Теперь эта структура данных и есть состояние. Дальше оно передаётся от функции к функции, сначала проходит через middleware-функции, потом в роутинг-функцию, потом в action-функцию контролера и т.д. пока эта структура-состояние не станет ответом.
Подождите, а как ЯП может запретить писать в каком-то стиле? Я всегда был уверен, что язык может только повысить удобство практического применения какой-то парадигмы, но запретить при этом все остальные… такого как-то не встречал.
Можете пример такого языка привести?
Не знаю, может там был дефицит других управляющих итерациями синтаксических конструкций… я уже с Паскаля начинал… там тоже был goto, но проблем от этого не было )
Всегда ведь можно сформулировать code convention, исходя из бизнес-требований. Бизнесов много и они разные, поэтому не уверен, что это на уровне разработчиков языка надо делать.
Просто "сайд-эффект" — это очень расплывчатое понятие. Некоторые даже нагрев процессора к ним относят :-)
С одной стороны можно считать сайд-эффектом любое действие внешнее к программе — запись в БД или в лог.
А с другой — только побочный/неожидаемый эффект от вызова функции. Когда Вы вызываете условно
db.insert!(comment), то это вполне ожидаемо приведёт к запросу к БД, а вот то, что этот же код приведёт к отправке email-уведомлений, отправит нотификацию в веб-сокет, а может и ещё что-то… вот это уже нифига неочевидно и обычно имеют в виду избежание именно сайд-эффектов такого типа.Если говорить о работе с разделяемой памятью, то используется модель акторов(запускается легковесный процесс, хранящий разделяемое состояние, а все остальные, чтобы повлиять на это состояние, шлют ему сообщения, которые применяются в порядке очереди). Вот тут можно почитать подробнее. Плюс недавно вышла хорошая статья на тему зачем вообще ФП в Erlang и Elixir
По-моему важно понимать, что если модели предметной области(классы, содержащие бизнес-логику), у вас не наследуют ActiveRecord::Base, то у вас нет паттерна ActiveRecord в проекте. Возможно вы используете рельсовый AR в качестве странной реализации паттерна Repository, возможно ещё как-то… но только не в качестве ActiveRecord.
При функциональном подходе обычно Virtual DOM является и входящим параметром, и результатом обработчиков. А реальный DOM скорее тем самым глобальным состоянием, которое напрямую никто не трогает.
Да любим мы состояния… проблема не в состояниях, а в работе с разделяемой памятью, особенно когда имеет место конкурентный доступ.
Для этого в функциональном подходе используют STM и Actor Model
Я для себя лично выбрал Elixir/Phoenix. Клиентской стороной я практически не занимаюсь, но вижу что Elm набирает популярность.
Т.е. Вы с проблемами от использования AR не сталкивались? И никаких неудобств от того, что логика предметной области находится в моделях AR не испытывали?
А причём тут религия? Вы же сами написали, что AR нигде толком не получился. Я только добавил, что он by design не может толком получиться и неизбежно будет доставлять проблемы в нетривиальных случаях.
Спорно. Всё-таки читабельность — это ответственность программиста. И выразительные средства языка ему в этом помогают.
А урезание выразительных возможностей наоборот снижает читабельность в сложных проектах. Для примера можно код крупных проектов на Go посмотреть.
В основном заворачивание побочных эффектов в монады, как попытка их изолировать.
Неа, глобальность — это как раз абсолютное понятие, и подразумевает оно доступность из любого места программы.
А то, что Вы описываете, называя глобальностью, — это по сути про вполне локальную область видимости.
После других языков самое непривычное в Ruby — это необязательность скобок (т.н. poetry mode)
Вообще вопросы синтаксиса — это очень субъективно… кто-то синтаксис Python терпеть не может из-за отсутствия
endили фигурных скобок, кому-тоdefв Ruby не нравится. Можно от всего этого абстрагироваться для решения какой-то единичной задачи, но при выборе языков для постоянного использования всё-таки важно, чтобы синтаксис был по душе.P.S. Если Вам нравится Python, то посмотрите ещё на Nim.
Я, правда, Вам ещё один ответ написал и только потом это сообщение увидел )))
Спасибо за дискуссию.
Ну вот, Вы сами описали как функции, одна за другой меняют состояние, которое передаётся по цепочке.
Состояние на уровне отдельной функции тоже можно рассматривать, так сказать, мгновенное состояние… но набор локальных «переменных» нас слабо волнует, интерес представляет только то состояние, которое передаётся по цепочке функций. По поводу всего остального мы просто ожидаем, что половину из этого компилятор нафиг уберёт, а остальное подчистит сборщик мусора )
Когда мы говорим, что данные неизменяемые, мы не лукавим, т.к. они физически не меняются в ОЗУ, в отличии от императивных языков. Насколько я понимаю, именно это помешало распространению ФП в прошлом веке, т.к. программы работали медленнее из-за неизменяемости данных, но со временем это оптимизировали. И теперь людей больше интересует как запустить сотни потоков и не получить ни race condition от доступа к изменяемым данным, ни геммороя с блокировками.
Давайте возьмём для примера веб-приложение, оно обрабатывает входящие HTTP-запросы. Задача приложения обработать запрос и выдать HTTP-ответ. Для простоты рассмотрим один поток выполнения. Получив запрос, приложение создаёт некоторую структуру данных, описывающую запрос. Теперь эта структура данных и есть состояние. Дальше оно передаётся от функции к функции, сначала проходит через middleware-функции, потом в роутинг-функцию, потом в action-функцию контролера и т.д. пока эта структура-состояние не станет ответом.
Можете пример такого языка привести?