Является ли дублирующий синтаксис для определения именованных функций плохим решением для проектирования языка?

9

Я забавляюсь языком программирования, и его синтаксис находится под сильным влиянием Scala, в частности определений функций.

Я столкнулся с проблемой проектирования, потому что мой язык не различает функции, определенные с помощью defсинтаксиса (методы класса), и анонимные функции, назначенные значениям (созданные с использованием =>) - он устраняет различия как в реализации, так и в поведении .

В результате два следующих определения означают одно и то же:

def square(x: Int) = x*x

val square = (x: Int) => x*x

Нет смысла использовать последнюю форму (немедленное анонимное назначение функции) в любой нормальной ситуации - ее просто можно использовать вместо defформы.

Повлияет ли наличие такого дублирующего синтаксиса для определения именованных функций на ортогональность языка или какой-либо другой аспект дизайна?

Я предпочитаю это решение, потому что оно допускает короткие и интуитивно понятные определения методов и именованных функций (через def), а также короткие определения анонимных функций (используя =>).

Редактировать: Scala делает различие между двумя - анонимные функции не совпадают с методами, определенными defв Scala. Различия относительно невелики - смотрите посты, на которые я ссылался ранее.

jcora
источник
However, assigning existing functionsкажется, отсутствует конец предложения
Изката
1
Можете ли вы определить рекурсивные функции, используя вашу valнотацию?
Джорджио
2
Я убедился, что это возможно и в Scala. В SML это не так, и вы должны использовать funдля определения рекурсивной функции.
Джорджио
3
Вторая форма - это на самом деле не особая синтаксическая структура def. Это просто побочный эффект того факта, что анонимная функция, скажем, (x : Int) => x + 1является объектом, и объектам можно присвоить значения с помощью val f = .... Разработчики языка должны были бы выйти из их пути , чтобы запретить синтаксис. Это не совсем то же самое, что явно приложить усилия для поддержки двух разных синтаксисов, которые делают (приблизительно) одно и то же.
KChaloux
3
Основное преимущество использования в языке чего-то более чем одним способом - это отличный способ начать непродуктивные религиозные дебаты, которые отвлекают от реальных проблем (Thinking C ++ здесь) .......
mattnz

Ответы:

3

Я думаю, что наличие двух конструкций, которые означают одно и то же, но выглядят по-разному, должно быть сведено к минимуму в языке. Любое дублирование увеличивает сложность чтения (и, следовательно, написания / изменения кода) на вашем языке. Устранение всего дублирования неизбежно в языке, который может создавать произвольные конструкции (например, эквивалентность итерации против рекурсии).

Так что в этом случае, я думаю, это может быть разработано лучше здесь. Единственный способ определения функций имеет для меня самый смысл. В этом случае это звучит так, как будто два оператора scala, которые у вас есть, на самом деле имеют несколько разные значения, что, опять же, вероятно, не очень хороший дизайн (вероятно, лучше всего иметь что-то ясное, в котором говорится о различиях, например, ключевое слово).

Фактически, вы можете применить этот принцип не только к именованным функциям, но и к любой функции. Почему есть разница в определении именованных функций и анонимных функций? В Лиме , функции всегда определяются следующим образом: fn[<arguments>: <statements>]. Если вы хотите, чтобы быть « под названием» вы можете присвоить его переменной: var x = fn[<arguments: <statements>], и если вы хотите , чтобы передать его в другой функции анонимно: function[fn[<arguments: <statements>]]. Если вы хотите, чтобы оно поднималось, сделайте его постоянным const var x = fn[<arguments: <statements>]. Одна форма делает очевидным, что они означают одно и то же.

BT
источник
Это довольно интересно, что constвызывает подъем, но это имеет смысл. В JS function myFuncвызывает подъем, но var myFunc =это не так, что, возможно, немного менее интуитивно понятно, поскольку в противном случае они ведут себя примерно так же.
mpen
1
@mpen Да, на самом деле javascript делает то же самое. function fnName()...форма делает на самом деле создать константу, которая является то , что делает грузоподъемным действительную вещь , чтобы сделать с ним. Javascript делает вещи довольно запутанными, когда вы используете форму, var fn = function anotherFnName()...так как это делает имя anotherFnName не подъемным, даже если оно явно постоянное.
BT
2

То, что вы опубликовали, является действительным Scala и работает нормально.

Учитывая, что удвоение не вызвало проблем со scala (насколько мне известно), я скажу, что это не будет проблемой и для вашего языка.

Daenyth
источник
1
Он действителен в Scala, в основном он работает одинаково, но это не означает одно и то же - и если вы приведете более сложные примеры (полиморфизм типов недоступен, например, для анонимных функций), различия станут более очевидными.
Jcora
2

Я обнаружил фундаментальную разницу между лямбдами и defметодами в Scala - я до сих пор не уверен, хочу ли я реализовать. Я должен провести дальнейшее исследование этого, и затем я сообщу о своем решении.

По сути, только методы могут return- и когда ключевое слово используется из лямбда-выражения, оно фактически возвращается из охватывающего метода.

Как я уже сказал, я не уверен, хочу ли я этого. Но это может быть достаточным оправданием для этого синтаксиса. Или, может быть, слишком опасно, потому что тонкие различия могут неожиданно причинить вред.

подробности

jcora
источник