Возможно, я ошибаюсь, поскольку никто не упомянул об этом, но у меня также сложилось впечатление, что причиной этого является также наследие ruby - возможность вызывать функции без скобок.
Arity явно вовлечен, но давайте отложим это на некоторое время и будем использовать функции без аргументов. В таком языке, как javascript, где скобки являются обязательными, легко сделать различие между передачей функции в качестве аргумента и вызовом функции. Вы называете это только тогда, когда используете скобки.
my_function // argument
(function() {}) // argument
my_function() // function is called
(function() {})() // function is called
Как видите, называть это или нет не имеет большого значения. Но эликсир и рубин позволяют вызывать функции без скобок. Это выбор дизайна, который мне лично нравится, но у него есть побочный эффект: вы не можете использовать только имя без скобок, потому что это может означать, что вы хотите вызвать функцию. Вот для чего &
. Если вы оставляете arity appart на секунду, добавление имени вашей функции &
означает, что вы явно хотите использовать эту функцию в качестве аргумента, а не то, что возвращает эта функция.
Теперь анонимная функция немного отличается тем, что она в основном используется в качестве аргумента. Опять же, это выбор дизайна, но рациональным является то, что он в основном используется функциями итераторов, которые принимают функции в качестве аргументов. Очевидно, что вам не нужно использовать, &
потому что они уже считаются аргументами по умолчанию. Это их цель.
Теперь последняя проблема заключается в том, что иногда вам приходится вызывать их в своем коде, потому что они не всегда используются с функцией итератора, или вы можете кодировать итератор самостоятельно. Для небольшой истории, поскольку ruby является объектно-ориентированным, основным способом сделать это было использование call
метода объекта. Таким образом, вы можете сохранить согласованность поведения необязательных скобок.
my_lambda.call
my_lambda.call()
my_lambda_with_arguments.call :h2g2, 42
my_lambda_with_arguments.call(:h2g2, 42)
Теперь кто-то придумал ярлык, который в основном выглядит как метод без имени.
my_lambda.()
my_lambda_with_arguments.(:h2g2, 42)
Опять же, это выбор дизайна. Теперь эликсир не является объектно-ориентированным и, следовательно, call не использует первую форму наверняка. Я не могу говорить за Хосе, но похоже, что вторая форма использовалась в эликсире, потому что она все еще выглядит как вызов функции с дополнительным символом. Это достаточно близко к вызову функции.
Я не думал обо всех плюсах и минусах, но похоже, что на обоих языках вы можете избежать неприятностей только с помощью скобок, если сделать скобки обязательными для анонимных функций. Кажется, что это так:
Обязательные скобки VS Немного отличные обозначения
В обоих случаях вы делаете исключение, потому что вы заставляете оба вести себя по-разному. Поскольку есть разница, вы можете также сделать это очевидным и перейти к другой записи. Обязательные скобки выглядят естественно в большинстве случаев, но очень запутанно, когда дела идут не так, как планировалось.
Ну вот. Возможно, это не лучшее объяснение в мире, потому что я упростил большинство деталей. Кроме того, большинство из них - выбор дизайна, и я попытался обосновать их, не осуждая их. Я люблю эликсир, я люблю рубин, мне нравятся вызовы функций без скобок, но, как и вы, я нахожу последствия весьма ошибочными время от времени.
А в эликсире это просто лишняя точка, тогда как в рубине у вас есть блоки поверх этого. Блоки удивительны, и я удивлен, как много вы можете сделать только с блоками, но они работают только тогда, когда вам нужна только одна анонимная функция, которая является последним аргументом. Тогда, поскольку вы должны иметь возможность иметь дело с другими сценариями, здесь возникает путаница в методе / lambda / proc / block.
Во всяком случае ... это выходит за рамки.