Спорно. Всё-таки читабельность — это ответственность программиста. И выразительные средства языка ему в этом помогают.
А урезание выразительных возможностей наоборот снижает читабельность в сложных проектах. Для примера можно код крупных проектов на 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-функцию контролера и т.д. пока эта структура-состояние не станет ответом.
Подождите, а как ЯП может запретить писать в каком-то стиле? Я всегда был уверен, что язык может только повысить удобство практического применения какой-то парадигмы, но запретить при этом все остальные… такого как-то не встречал.
Можете пример такого языка привести?
А где вы вообще вычитали про неизменяемое состояние в ФП? В ФП есть неизменяемость данных, но причём тут состояние?
Любая функция, если она что-то делает изменяет состояние, это вроде очевидный факт касаемо ФП.
Даже чисто математические функции изменяют состояние:
y(x) = x*x
y(5) => 25 // было состояние: 5, стало: 25.
Разница в том, что в ФП это состояние передаётся в качестве аргумента функции, а в ООП состояние — это отдельная «сущность», на которую 2 метода могут влиять параллельно.
Зачем править, когда есть monkey-patching :-D
А если серьёзно, то всё-таки ситуация получше, каждый первый точно править не надо. В основном в допилке нуждаются не особо популярные гемы типа интеграций со всякими сервисами. Случаи, когда нужно влезть в исходники того же Arel или kaminari, не так уж часто встречаются.
Если коротко, то состояние передаётся от функции к функции. Каждая функция его меняет (или не меняет, если надо пропустить шаг обработки) и передаёт следующей.
Вы маленько путаете… Программы, полезные с практической точки зрения, действительно содержат сайд-эффекты, такие как запись в БД. Но из популярных нынче ФП, насколько мне известно, только Haskell радеет за чистоту в этом смысле.
Остальные относятся к этому проще, представляя программу как своеобразный конвеер, у которого на входе — запрос, на выходе — ответ. А внутри цепочка функций, шаг за шагом преобразующих то самое состояние. Некоторые из этих функций могут иметь побочный эффект в виде записи в персистентное хранилище.
Ну а то, что пишут в императивном стиле и в нечитабельной форме, то это ведь не проблема ФП, это проблема с ригидностью мышления автора конкретного кода. ФП — не самоцель, а один из удобных инструментов, если уметь им пользоваться.
Более подходящее выражение: выход из зоны комфорта. Если для Rails у Вас уже есть набор привычных гемов. То тут придётся этот набор заново подбирать и возможно что-то самому писать. Я просто застал время, когда и используя Rails надо было самому писать гемы. Поэтому не вижу в этом ничего страшного :-)
Да не, эта идиома переводится именно так: пруф. Другое дело, что дословный перевод был в чём-то яснее, т.к. выражение «из коробки» уже устоялось в IT и понятно о какой «коробке» идёт речь.
Спорно. Всё-таки читабельность — это ответственность программиста. И выразительные средства языка ему в этом помогают.
А урезание выразительных возможностей наоборот снижает читабельность в сложных проектах. Для примера можно код крупных проектов на Go посмотреть.
В основном заворачивание побочных эффектов в монады, как попытка их изолировать.
Неа, глобальность — это как раз абсолютное понятие, и подразумевает оно доступность из любого места программы.
А то, что Вы описываете, называя глобальностью, — это по сути про вполне локальную область видимости.
После других языков самое непривычное в Ruby — это необязательность скобок (т.н. poetry mode)
Вообще вопросы синтаксиса — это очень субъективно… кто-то синтаксис Python терпеть не может из-за отсутствия
endили фигурных скобок, кому-тоdefв Ruby не нравится. Можно от всего этого абстрагироваться для решения какой-то единичной задачи, но при выборе языков для постоянного использования всё-таки важно, чтобы синтаксис был по душе.P.S. Если Вам нравится Python, то посмотрите ещё на Nim.
Я, правда, Вам ещё один ответ написал и только потом это сообщение увидел )))
Спасибо за дискуссию.
Ну вот, Вы сами описали как функции, одна за другой меняют состояние, которое передаётся по цепочке.
Состояние на уровне отдельной функции тоже можно рассматривать, так сказать, мгновенное состояние… но набор локальных «переменных» нас слабо волнует, интерес представляет только то состояние, которое передаётся по цепочке функций. По поводу всего остального мы просто ожидаем, что половину из этого компилятор нафиг уберёт, а остальное подчистит сборщик мусора )
Когда мы говорим, что данные неизменяемые, мы не лукавим, т.к. они физически не меняются в ОЗУ, в отличии от императивных языков. Насколько я понимаю, именно это помешало распространению ФП в прошлом веке, т.к. программы работали медленнее из-за неизменяемости данных, но со временем это оптимизировали. И теперь людей больше интересует как запустить сотни потоков и не получить ни race condition от доступа к изменяемым данным, ни геммороя с блокировками.
Давайте возьмём для примера веб-приложение, оно обрабатывает входящие HTTP-запросы. Задача приложения обработать запрос и выдать HTTP-ответ. Для простоты рассмотрим один поток выполнения. Получив запрос, приложение создаёт некоторую структуру данных, описывающую запрос. Теперь эта структура данных и есть состояние. Дальше оно передаётся от функции к функции, сначала проходит через middleware-функции, потом в роутинг-функцию, потом в action-функцию контролера и т.д. пока эта структура-состояние не станет ответом.
Можете пример такого языка привести?
Любая функция, если она что-то делает изменяет состояние, это вроде очевидный факт касаемо ФП.
Даже чисто математические функции изменяют состояние:
y(x) = x*x
y(5) => 25 // было состояние: 5, стало: 25.
Разница в том, что в ФП это состояние передаётся в качестве аргумента функции, а в ООП состояние — это отдельная «сущность», на которую 2 метода могут влиять параллельно.
А если серьёзно, то всё-таки ситуация получше, каждый первый точно править не надо. В основном в допилке нуждаются не особо популярные гемы типа интеграций со всякими сервисами. Случаи, когда нужно влезть в исходники того же Arel или kaminari, не так уж часто встречаются.
Остальные относятся к этому проще, представляя программу как своеобразный конвеер, у которого на входе — запрос, на выходе — ответ. А внутри цепочка функций, шаг за шагом преобразующих то самое состояние. Некоторые из этих функций могут иметь побочный эффект в виде записи в персистентное хранилище.
Ну а то, что пишут в императивном стиле и в нечитабельной форме, то это ведь не проблема ФП, это проблема с ригидностью мышления автора конкретного кода. ФП — не самоцель, а один из удобных инструментов, если уметь им пользоваться.