Después de mirar algunos lenguajes para la programación funcional, siempre me pregunté por qué algunos lenguajes fp usan uno o más caracteres de espacios en blanco para la aplicación de funciones (y definición), mientras que la mayoría (¿todos?) De los lenguajes imperativos / orientados a objetos están usando paréntesis, lo que parece Ser la forma más matemática. También creo que este último estilo es mucho más claro y legible que sin los parens.
Entonces, si tenemos una función f (x) = x², existen dos alternativas para llamarla:
FP:
f x
Ejemplos:
- ML, Ocaml, F #
- Haskell
- LISP, Esquema (de alguna manera)
No FP:
f(x)
Ejemplos:
- Casi todos los idiomas imperativos (lo sé, vea los comentarios / respuestas)
- Erlang
- Scala (también permite "notación de operador" para argumentos individuales)
¿Cuáles son las razones para "dejar de lado" los paréntesis?
x²
como ejemplo?Respuestas:
Los lenguajes funcionales están inspirados en el cálculo lambda . En este campo, los paréntesis no se utilizan para la aplicación de funciones.
La legibilidad está en el ojo del espectador. No estás acostumbrado a leerlo. Es un poco como los operadores matemáticos. Si comprende la asociatividad, solo necesita unos pocos padres para aclarar la estructura de su expresión. A menudo no los necesitas.
El curry también es una buena razón para usar esta convención. En haskell, puede definir lo siguiente:
Con parens, puede usar dos convenciones:
f(5, 6)
(no curry) of(5)(6)
(curry). La sintaxis de Haskell ayuda a acostumbrarse al concepto de curry. Todavía puede usar una versión sin curry, pero es más doloroso usarla con combinadoresObserve cómo la segunda versión lo obliga a registrar x como una variable, y que la subexpresión es una función que toma un número entero y le agrega 5. La versión al curry es mucho más ligera, pero también es considerada por muchos como más legible.
Los programas Haskell hacen un uso extensivo de aplicaciones parciales y combinadores como un medio para definir y componer abstracciones, por lo que este no es un ejemplo de juguete. Una buena interfaz de función será aquella en la que el orden de los parámetros proporcione un uso curioso amigable.
Otro punto: una función sin parámetros debe llamarse con
f()
. En Haskell, dado que solo manipula valores evaluados perezosos inmutables, simplemente escribef
y lo considera como un valor que necesitará realizar algunos cálculos cuando sea necesario. Como su evaluación no tendrá ningún efecto secundario, no tiene sentido tener una notación diferente para la función sin parámetros y su valor devuelto.También hay otras convenciones para la aplicación de funciones:
fuente
f(a, ,b)
oadd(a, )
, oadd(, b)
parecería más flexible de manera predeterminada.La idea básica es hacer que la operación más importante (aplicación de función) sea más fácil de leer y más fácil de escribir. Un espacio es muy poco intrusivo para leer y muy fácil de escribir.
Tenga en cuenta que esto no es específico para los lenguajes funcionales, por ejemplo, en Smalltalk , uno de los primeros lenguajes e idiomas OO inspirados en él ( Self , Newspeak , Objective-C), sino también en Io e idiomas inspirados en él (Ioke, Seph), el espacio en blanco se usa para llamadas a métodos.
Estilo Smalltalk:
(En el último caso, el nombre del método es
replace:with:
).Io-style:
Scala también permite espacios en blanco para llamadas a métodos:
Y omitiendo los paréntesis si solo hay un argumento:
Ruby también te permite dejar los paréntesis:
Realmente no:
La notación matemática ha evolucionado durante mucho tiempo de una manera terriblemente inconsistente.
En todo caso, los lenguajes funcionales se inspiran en el cálculo λ donde la aplicación de funciones se escribe utilizando espacios en blanco.
fuente
El paréntesis para la aplicación de funciones es solo uno de los muchos sillines que nos dejó Euler. Como cualquier otra cosa, las matemáticas necesitan convenciones cuando hay varias formas de hacer algo. Si su educación matemática solo se extiende hasta una materia no matemática en la universidad, entonces probablemente no esté demasiado familiarizado con los muchos campos en los que la aplicación de funciones ocurre felizmente sin ninguno de estos corchetes sin sentido (por ejemplo, Geometría diferencial, Álgebra abstracta). Y ni siquiera menciona funciones que se aplican infijo (casi todos los idiomas), "outfix" como tomar una norma, o esquemáticamente (Befunge, Topología algebraica).
Entonces, en respuesta, diría que se debe a una proporción mucho mayor de programadores funcionales y diseñadores de lenguaje que tienen una amplia educación matemática. Von Neumann dice: "Joven, en matemáticas no entiendes las cosas. Simplemente te acostumbras a ellas", ciertamente esto es cierto para la notación.
fuente
f(x)
vs.sin x
vs.x²
vs.|x|
vs.x!
vs.x + y
vs.xy
vs.½
vs. un resumen vs. un integral vs.…Aunque hay mucha verdad en la respuesta de Simon, creo que también hay una razón mucho más práctica. La naturaleza de la programación funcional tiende a generar muchos más paréntesis que la programación imperativa, debido al encadenamiento de funciones y la composición. Esos patrones de encadenamiento y composición también pueden ser representados sin ambigüedades sin paréntesis.
La conclusión es que todos esos paréntesis se vuelven molestos de leer y rastrear. Probablemente sea la razón número uno por la que LISP no es más popular. Entonces, si puede obtener el poder de la programación funcional sin la molestia del paréntesis en exceso, creo que los diseñadores de lenguaje tenderán a ir de esa manera. Después de todo, los diseñadores de idiomas también son usuarios de idiomas.
Incluso Scala permite al programador omitir paréntesis en ciertas circunstancias, que aparecen con bastante frecuencia cuando se programa en un estilo funcional, por lo que obtienes lo mejor de ambos mundos. Por ejemplo:
Los parens al final son necesarios para la asociatividad, y los demás se dejan (así como los puntos). Escribirlo de esta manera enfatiza la naturaleza encadenada de las operaciones que está realizando. Puede que no sea familiar para un programador imperativo, pero para un programador funcional se siente muy natural y fluido escribir de esta manera, sin tener que detener e insertar una sintaxis que no agrega significado al programa, pero está ahí para hacer feliz al compilador .
fuente
Ambas premisas están equivocadas.
Estos lenguajes funcionales no usan espacio para la aplicación de funciones. Lo que hacen es simplemente analizar cualquier expresión que viene después de una función como argumento.
Por supuesto, si se utiliza ni un espacio ni parens entonces normalmente no funciona, simplemente porque la expresión no está adecuadamente tokenised
Pero si estos idiomas estuvieran restringidos a nombres de variables de 1 carácter, entonces también funcionaría.
Las convenciones matemáticas tampoco requieren normalmente paréntesis para la aplicación de funciones. No solo los matemáticos a menudo escriben sen x : para funciones lineales (generalmente llamadas operadores lineales), también es muy habitual escribir el argumento sin parens, tal vez porque (al igual que cualquier función en la programación funcional) las funciones lineales a menudo se manejan sin suministrar directamente un argumento.
Entonces, realmente, su pregunta se reduce a: ¿por qué algunos idiomas requieren paréntesis para la aplicación de funciones? Bueno, aparentemente algunas personas, como tú, consideran que esto es más legible. Estoy totalmente en desacuerdo con eso: un par de padres es agradable, pero tan pronto como haya anidado más de dos, comienza a ser confuso. El código de Lisp demuestra esto mejor, y casi todos los lenguajes funcionales se verían igualmente desordenados si necesitaras parens en todas partes. Esto no sucede tanto en los idiomas imperativos, sino principalmente porque estos idiomas no son lo suficientemente expresivos como para escribir frases claras y concisas en primer lugar.
fuente
object method: args
, Objective C tiene[object method: args]
, y Ruby y Perl permiten omitir paréntesis en llamadas a funciones y métodos, solo requiriendo que resuelvan la ambigüedad.Una pequeña aclaración histórica: ¡la notación original en matemáticas no tenía paréntesis !
La notación fx para una función arbitraria de x fue introducida por Johan Bernoulli alrededor de 1700, poco después de que Leibniz comenzó a hablar de funciones (en realidad, Bernoulli escribió ϕ x ). Pero antes de eso, muchas personas ya usaban anotaciones como sen x o lx (el logaritmo de x ) para funciones específicas de x , sin paréntesis. Sospecho que esa es la razón por la que muchas personas todavía escriben sin x en lugar de sin (x) .
Euler, que era estudiante de Bernoulli, adoptó Bernoulli de φ x y cambió el griego en una letra latina, escribiendo fx . Más tarde se dio cuenta de que podría ser fácil confundir f por una "cantidad" y creer que fx era un producto, por lo que comenzó a escribir f: x . Por lo tanto, la notación f (x) no se debe a Euler. Por supuesto, Euler necesitaba paréntesis por la misma razón que todavía necesitamos paréntesis en lenguajes de programación funcionales: para distinguir, por ejemplo, (fx) + y de f (x + y) . Sospecho que las personas después de que Euler adoptó el paréntesis como predeterminado porque vieron principalmente a Euler escribir expresiones compuestas como f (ax + b). Raramente escribía solo fx .
Para más información sobre esto, vea: ¿Euler escribió alguna vez f (x) entre paréntesis? .
No sé si los diseñadores de lenguajes de programación funcionales o los inventores del cálculo lambda estaban al tanto de las raíces históricas de su notación. Personalmente, encuentro la notación sin paréntesis más natural.
fuente