¿La sintaxis duplicada para definir funciones con nombre es una mala decisión de diseño de lenguaje?

9

Estoy modelando un lenguaje de programación por diversión, y la sintaxis está fuertemente influenciada por Scala, específicamente las definiciones de funciones.

Me he encontrado con un problema de diseño porque mi lenguaje no diferencia entre las funciones definidas a través de la defsintaxis (métodos de clase) y las funciones anónimas asignadas a los valores (creados usando =>): elimina las diferencias tanto en la implementación como en el comportamiento .

El resultado es que las siguientes dos definiciones significan lo mismo:

def square(x: Int) = x*x

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

No hay ninguna razón para usar esta última forma (asignación de función anónima inmediata) en cualquier situación normal; simplemente es posible usarla en lugar de la defforma.

¿Tener una sintaxis duplicada para definir funciones con nombre dañaría la ortogonalidad del lenguaje o algún otro aspecto del diseño?

Prefiero esta solución porque permite definiciones cortas e intuitivas de métodos y funciones con nombre (vía def), y definiciones cortas de funciones anónimas (usando =>).

Editar: Scala hace diferenciar entre los dos - anónimo funciones no son las mismas que con los métodos definidos defen Scala. Sin embargo, las diferencias son relativamente sutiles: vea las publicaciones que he vinculado antes.

jcora
fuente
However, assigning existing functionsparece faltar el final de la oración
Izkata
1
¿Puedes definir funciones recursivas usando tu valnotación?
Giorgio
2
Verifiqué que esto también es posible en Scala. En SML no lo es y debe usarlo funpara definir una función recursiva.
Giorgio
3
La segunda forma no es realmente una estructura sintáctica especial, la forma defes. Es solo un efecto secundario del hecho de que una función anónima, digamos, (x : Int) => x + 1es un objeto, y los objetos pueden asignarse a valores con val f = .... Los diseñadores del lenguaje habrían tenido que salir de su camino para no permitir la sintaxis. No es lo mismo que hacer un esfuerzo explícito para admitir dos sintaxis diferentes que hacen (aproximadamente) lo mismo.
KChaloux
3
El principal beneficio de hacer algo más de una manera en un idioma es que es una excelente manera de iniciar debates religiosos improductivos que distraen de los problemas reales (Pensar C ++ aquí) .......
mattnz

Respuestas:

3

Creo que tener dos construcciones que signifiquen lo mismo pero se vean diferentes debería mantenerse al mínimo en un idioma. Cualquier duplicación aumenta lo difícil que es leer (y por lo tanto escribir / modificar código) en su idioma. Eliminar toda duplicación es inevitable en un lenguaje que puede crear construcciones arbitrarias (por ejemplo, la equivalencia de iteración frente a recursión).

Entonces, en este caso, creo que podría diseñarse mejor aquí. Una sola forma de definir funciones tiene más sentido para mí. En este caso, parece que las dos afirmaciones de escala que tiene realmente tienen implicaciones ligeramente diferentes, lo que de nuevo probablemente no sea un buen diseño (probablemente sea mejor tener algo claro que indique cuáles son las diferencias, como una palabra clave).

De hecho, puede aplicar este principio no solo a las funciones con nombre, sino a cualquier función. ¿Por qué hay alguna diferencia en la definición de funciones con nombre y funciones anónimas? En Lima , las funciones siempre se definen así: fn[<arguments>: <statements>]. Si usted quiere que sea "llamado" se puede asignar a una variable: var x = fn[<arguments: <statements>]y si quieres pasarlo a otra función anónima: function[fn[<arguments: <statements>]]. Si lo quieres izar, hazlo constante const var x = fn[<arguments: <statements>]. La forma única hace obvio que significan lo mismo.

BT
fuente
Eso es bastante interesante que constcausa la elevación, pero tiene mucho sentido. En JS function myFuncprovoca la elevación, pero var myFunc =no lo hace, lo cual es quizás un poco menos intuitivo porque de lo contrario se comportan de la misma manera.
mpen
1
@mpen Sí, en realidad, JavaScript esencialmente hace lo mismo. De hecho, la function fnName()...forma crea una constante, que es lo que hace que la elevación sea algo válido que ver con ella. Javascript hace que las cosas sean bastante confusas cuando usas el formulario, var fn = function anotherFnName()...ya que eso hace que el nombre anotherFnName no se levante, incluso si es claramente constante.
BT
2

Lo que has publicado es scala válido y funciona bien.

Dado que la duplicación no ha causado problemas con scala (que yo sepa), voy a decir que tampoco será un problema para su idioma.

Daenyth
fuente
1
Es válido en Scala, en su mayoría funciona igual, pero no significa lo mismo, y si hiciera ejemplos más complejos (el polimorfismo de tipo no está disponible para funciones anónimas, por ejemplo), las diferencias serían más evidentes.
jcora
2

He encontrado una diferencia fundamental entre lambdas y defmétodos en Scala: que todavía no estoy seguro de si quiero implementar. Tengo que investigar más al respecto y luego informaré sobre mi decisión.

Esencialmente, solo los métodos pueden return, y cuando la palabra clave se usa desde una lambda, en realidad regresa del método que lo abarca.

Como he dicho, no estoy seguro de si quiero esto. Pero podría ser justificación suficiente para esta sintaxis. O tal vez demasiado peligroso porque las diferencias sutiles pueden causar daño inesperadamente.

Detalles

jcora
fuente