Посмотрев на некоторые языки для функционального программирования, я всегда задавался вопросом, почему некоторые языки fp используют один или несколько пробельных символов для приложения функции (и определения), тогда как большинство (все?) Императивных / объектно-ориентированных языков используют круглые скобки, которые, кажется, быть более математическим путем. Я также думаю, что последний стиль намного более понятен и читабелен, чем без паренов.
Поэтому, если у нас есть функция f (x) = x², есть две альтернативы ее вызову:
FP:
f x
Примеры:
- ML, Ocaml, F #
- Haskell
- ЛИСП, Схема (как-то)
Non-FP:
f(x)
Примеры:
- Почти все императивные языки (я знаю, см. Комментарии / ответы)
- Erlang
- Scala (также допускает «нотацию оператора» для отдельных аргументов)
Каковы причины "опущения" скобок?
x²
в качестве примера?Ответы:
функциональные языки основаны на лямбда-исчислении . В этом поле круглые скобки не используются для применения функции.
Читаемость в глазах смотрящего. Вы не привыкли это читать. Это немного похоже на математические операторы. Если вы понимаете ассоциативность, вам нужно всего несколько парен, чтобы прояснить структуру вашего выражения. Часто они вам не нужны.
Карри также является хорошей причиной для использования этого соглашения. В haskell вы можете определить следующее:
С паренсом вы можете использовать два соглашения:
f(5, 6)
(не карри) илиf(5)(6)
(карри). Синтаксис haskell помогает привыкнуть к концепции карри. Вы все еще можете использовать версию без карри, но более болезненно использовать ее с комбинаторамиОбратите внимание, как вторая версия заставляет вас регистрировать x как переменную, и что подвыражение является функцией, которая принимает целое число и добавляет к нему 5? Карри версия намного легче, но многие считают ее более читабельной.
Программы на Haskell широко используют частичное применение и комбинаторы как средство определения и составления абстракций, так что это не игрушечный пример. Хороший функциональный интерфейс будет таким, где порядок параметров обеспечивает удобное каррирование.
Еще один момент: функцию без параметров следует вызывать с помощью
f()
. В haskell, поскольку вы манипулируете только неизменяемыми значениями с отложенным вычислением, вы просто пишетеf
и рассматриваете его как значение, которое потребуется для выполнения некоторых вычислений при необходимости. Поскольку его оценка не будет иметь никакого побочного эффекта, нет смысла иметь другое обозначение для функции без параметров и ее возвращаемого значения.Есть и другие соглашения для применения функции:
источник
f(a, ,b)
илиadd(a, )
илиadd(, b)
будет казаться более гибкими по умолчанию.Основная идея состоит в том, чтобы сделать наиболее важную операцию (функциональное приложение) наиболее легкой для чтения и самой легкой для записи. Пробел очень ненавязчив и удобен для чтения.
Обратите внимание, что это относится не только к функциональным языкам, например к Smalltalk , одному из первых ОО-языков и языков, вдохновленных им ( Self , Newspeak , Objective-C), но также к Io и языкам, вдохновленным им (Ioke, Seph), пробел используется для вызова методов.
Smalltalk-стиль:
(В последнем случае название метода
replace:with:
.)Io-стиль:
Scala также позволяет использовать пробелы для вызовов методов:
И опуская скобки, если есть только один аргумент:
Ruby также позволяет убрать скобки:
На самом деле, нет:
Математические обозначения развивались в течение долгого времени ужасно непоследовательным образом.
Если это вообще так, функциональные языки черпают вдохновение из λ-исчисления, где приложение функции написано с использованием пробела.
источник
Скобки для приложения функций - лишь одно из многих седел, с которыми нам пришлось столкнуться Эйлеру. Как и все остальное, математика нуждается в соглашениях, когда есть несколько способов что-то сделать. Если ваше математическое образование распространяется только на нематематический предмет в университете, то вы, вероятно, не слишком знакомы со многими областями, в которых применение функций происходит без каких-либо из этих бессмысленных скобок (например, дифференциальная геометрия, абстрактная алгебра). И вы даже не упомянули функции, которые применяются в инфиксном (почти на всех языках), «нарезаемом», например, принимают норму, или схематично (Befunge, алгебраическая топология).
Поэтому в ответ я бы сказал, что это связано с гораздо большей долей функциональных программистов и разработчиков языков, имеющих обширное математическое образование. Фон Нейманн говорит: «Молодой человек, в математике ты ничего не понимаешь. Ты просто привыкаешь к ним», конечно, это верно для обозначения.
источник
f(x)
против:sin x
против,x²
против,|x|
против,x!
против,x + y
против,xy
против½
суммирования, против интеграла, против ...Хотя в ответе Саймона много правды, я думаю, что есть и более практическая причина. Природа функционального программирования имеет тенденцию генерировать намного больше скобок, чем императивное программирование, из-за цепочки функций и композиции. Эти схемы сцепления и композиции также, как правило, могут быть однозначно представлены без скобок.
Суть в том, что все эти скобки надоедают читать и отслеживать. Вероятно, это причина номер один, почему LISP не так популярен. Так что, если вы можете получить всю мощь функционального программирования без раздражения из-за лишних скобок, я думаю, что разработчики языка будут стремиться пойти по этому пути. В конце концов, языковые дизайнеры также являются языковыми пользователями.
Даже Scala позволяет программисту опускать круглые скобки в определенных обстоятельствах, которые довольно часто встречаются при программировании в функциональном стиле, так что вы как бы получаете лучшее из обоих миров. Например:
Парены в конце необходимы для ассоциативности, а остальные не учитываются (как и точки). Написание этого текста подчеркивает цепную природу операций, которые вы выполняете. Это может быть не знакомо императивному программисту, но функциональному программисту кажется очень естественным и плавным писать таким образом, без необходимости останавливаться и вставлять синтаксис, который не добавляет смысла программе, а просто делает его счастливым для компилятора. ,
источник
Оба предположения неверны.
Эти функциональные языки не используют пространство для приложения функций. Они просто анализируют любое выражение, которое идет после функции, в качестве аргумента.
Конечно, если вы не используете ни пробел, ни паренсы, то обычно это не сработает, просто потому, что выражение неправильно маркировано
Но если бы эти языки были ограничены именами переменных из 1 символа, это тоже сработало бы.
Математические соглашения также обычно не требуют скобок для применения функций. Математики не только часто пишут sin x - для линейных функций (обычно называемых тогда линейными операторами) также очень часто пишут аргументы без паренов, возможно потому, что (как и любая функция в функциональном программировании) линейные функции часто обрабатываются без прямой поставки Аргумент.
Так что на самом деле ваш вопрос сводится к следующему: почему для некоторых языков требуются скобки для применения функций? Ну, видимо, некоторые люди, такие как вы, считают это более читабельным. Я категорически не согласен с этим: одна пара паренов хороша, но как только у вас будет больше двух из них, она начинает сбивать с толку. Код на Лиспе демонстрирует это наилучшим образом, и почти все функциональные языки выглядят одинаково загроможденными, если вам нужны паренсы везде. В императивных языках это происходит не так часто, но в основном потому, что эти языки недостаточно выразительны, чтобы в первую очередь писать краткие, понятные строки.
источник
object method: args
, Objective C имеет[object method: args]
, и Ruby и Perl оба позволяют опускать круглые скобки в вызовах функций и методов, требуя только разрешения неоднозначности.Небольшое историческое уточнение: оригинальная запись в математике была без скобок !
Обозначение fx для произвольной функции x было введено Йоханом Бернулли около 1700 года, вскоре после того, как Лейбниц начал говорить о функциях (фактически Бернулли написал ϕ x ). Но до этого многие люди уже использовали такие обозначения, как sin x или lx (логарифм x ) для определенных функций x без скобок. Я подозреваю, что это причина, по которой многие люди до сих пор пишут грех х вместо греха (х) .
Эйлер, который был студентом Бернулли, принял Бернулли ϕ x и изменил греческое на латинское письмо, написав fx . Позже он заметил, что было бы легко спутать f с «количеством» и поверить, что fx был продуктом, поэтому он начал писать f: x . Следовательно, обозначение f (x) не принадлежит Эйлеру. Конечно, Эйлер нуждался в круглых скобках по той же причине, по которой нам все еще нужны круглые скобки в функциональных языках программирования: например, чтобы отличить (fx) + y от f (x + y) . Я подозреваю, что люди после Эйлера приняли скобки по умолчанию, потому что они в основном видели, как Эйлер писал составные выражения типа f (ax + b), Он редко писал только FX .
Более подробно об этом см .: Эйлер когда-нибудь писал f (x) с круглыми скобками? ,
Я не знаю, знали ли разработчики функциональных языков программирования или изобретатели лямбда-исчисления об исторических корнях их обозначений. Лично я считаю нотацию без скобок более естественной.
источник