¿Por qué la sintaxis funcional del lenguaje no se acerca más al lenguaje humano?

14

Estoy interesado en la programación funcional y decidí enfrentarme a Haskell. Me duele la cabeza ... pero eventualmente lo tendré ... Sin embargo, tengo una curiosidad, ¿por qué la sintaxis es tan críptica (a falta de otra palabra)?

¿Hay alguna razón por la cual no es más expresivo , más cercano al lenguaje humano?

Entiendo que FP es bueno para modelar conceptos matemáticos y tomó prestados algunos de sus concisos medios de expresión, pero aún así no es matemática ... es un lenguaje.

JohnDoDo
fuente
44
@ratchet freak: :) entonces, ¿hay uno diseñado por un tipo que odia la notación polaca?
JohnDoDo
10
@ratchetfreak ¿De qué manera la sintaxis de Haskell se parece a la notación polaca? Los operadores de Haskell tienen infijo, al igual que la mayoría de los operadores de otros idiomas (y las llamadas de función son prefijas, también como la mayoría de las llamadas de función de otros idiomas).
sepp2k
99
Esa es una suposición / salto bastante grande que estás haciendo, que "más cercano al lenguaje humano" equivale a "más expresivo".
Matt Ball
77
¿Has oído hablar de Cobol y Fortran?
ott--
77
Exactamente por la misma razón que los matemáticos reemplazaron las largas frases latinas con expresiones algebraicas. Con un poco de práctica, una notación más compacta es mucho más productiva.
Kevin Cline

Respuestas:

14

Lenguajes funcionales como Haskell y su antecedente Miranda surgieron del concepto matemático del cálculo lambda . Desde la página de Wikipedia:

El cálculo lambda (también escrito como cálculo λ o llamado "cálculo lambda") es un sistema formal en lógica matemática para expresar la computación mediante la vinculación y la sustitución de variables.

...

El cálculo de Lambda ha jugado un papel importante en el desarrollo de la teoría de los lenguajes de programación. Las contrapartes más destacadas del cálculo lambda en informática son los lenguajes de programación funcionales, que esencialmente implementan el cálculo (aumentado con algunas constantes y tipos de datos). Más allá de los lenguajes de programación, el cálculo lambda también tiene muchas aplicaciones en la teoría de pruebas. Un ejemplo importante de esto es la correspondencia de Curry-Howard, que proporciona una correspondencia entre diferentes sistemas de cálculo lambda mecanografiado y sistemas de lógica formal.

Debido a esta historia, las sintaxis de estos lenguajes funcionales (y elementos funcionales de lenguajes más imperativos) están fuertemente influenciados por la notación matemática utilizada por el cálculo lambda.

La precisión con la que tanto las anotaciones matemáticas como los lenguajes de computadora pueden describir los requisitos y la precisión con que las computadoras requieren que sus instrucciones estén escritas se correlacionan bien entre sí. Sin embargo, la imprecisión del lenguaje natural crea una gran barrera para su uso en la programación de computadoras. Incluso los entornos de programación de lenguaje natural (posiblemente) más exitosos , como Wolfram Alpha, necesitan una experiencia de dominio significativa para ser utilizados de manera efectiva.

Mark Booth
fuente
29

La sintaxis de Haskell está cerca del lenguaje humano. Está específicamente diseñado para parecerse a la notación matemática, que es un lenguaje diseñado por humanos (por lo tanto, un lenguaje humano ) para expresar con precisión aquellos conceptos sobre los que se basa Haskell.

Puede mostrar un fragmento de código de Haskell a cualquier matemático o lógico, y él podrá entenderlo, incluso si nunca ha oído hablar de Haskell y no sabe absolutamente nada sobre programación, ciencias de la computación o incluso computadoras.

Por otro lado, puede mostrarle a cualquier matemático o lógico un código como este:

x = x + 1

y estará completamente confundido, diciendo: "Esto no tiene sentido, no hay xtal que sea xigual a xmás 1".

Si una notación específica es o no "críptica" o no, es una cuestión de opinión y familiaridad.

Jörg W Mittag
fuente
8
Solo hay un problema con esta respuesta: no soy matemático.
JohnDoDo
66
@ sepp2k: No estoy de acuerdo. Para la mayoría de la gente w / o la exposición previa a los lenguajes de programación y algunos conocimientos matemáticos básicos sintaxis de Haskell será mucho más sencillo de entender que el código procedual típica con todos sus efectos secundarios y los entornos complicados declaraciones se ejecutan en. Sintaxis como wherepermite condensar la esencia de Una función en una línea.
Benjamin Bannier el
17
-1: esta respuesta parece en gran medida pedante. Estoy bastante seguro de que el OP significaba lenguaje hablado.
Steven Evers
66
En realidad, estoy bastante seguro de que eso x = infinityresuelve la ecuación.
DeadMG
66
Bueno, los lenguajes de programación también están diseñados por humanos ... Por lo tanto, según su definición, son lenguajes humanos.
marco-fiset
13

Creo que una cosa con la que probablemente te estés encontrando es algo con lo que me encontré también cuando aprendí la programación funcional, que es que con la programación funcional puedes (y casi tienes que) pensar / trabajar a un nivel más alto que con la programación imperativa.

Creo que lo que está encontrando como menos expresivo es en realidad más expresivo: no tiene que detallar cada pequeño detalle y puede hacer más con menos código en la programación funcional: hay más poder en lo que escribe.

Por ejemplo, podría escribir imperativamente:

for each (Person person in people)
    print(person.name)

lo cual es totalmente legible como inglés.

Una versión de Haskell podría ser (y esto no es válido para Haskell, pero es solo para comparación sintáctica):

map (print . name) people

que requiere menos código y menos discusión de detalles: no tengo que dividir las cosas en un bucle y sus variables ( for each (...)), la mapfunción se encarga de eso por mí.

Trabajar a ese nivel puede llevar un tiempo acostumbrarse. Si ayuda, Haskell fue probablemente el momento más difícil que he tenido aprendiendo un nuevo lenguaje desde que comencé a programar, y sé> 10 idiomas (incluido Lisp). Sin embargo, valió la pena aprenderlo.

Pablo
fuente
8

Actualmente me estoy familiarizando con Scala en este momento, así que puedo simpatizar. Al menos con Scala puedo recurrir a un estilo imperativo cuando las cosas se ponen difíciles.

Creo que hay varias fuerzas en juego aquí:

  • Los diseñadores de lenguajes funcionales necesariamente tienen una sólida formación matemática, por lo que toman prestada una notación matemática que es natural para ellos.

  • La mayor expresividad (es decir, el poder de las declaraciones, en lugar de la cercanía al inglés) de cualquier idioma tiene (IMO) un precio correspondiente en la curva de aprendizaje. La terquedad es una calidad muy apreciada en Scala, con muchas cosas que son opcionales.

  • Los lenguajes funcionales simplemente hacen las cosas de manera muy diferente, por lo que las operaciones básicas no se asignan a construcciones imperativas.

Richard Close
fuente
3
También agregaría que a menudo los lenguajes funcionales pueden expresar conceptos de orden superior, siendo estos más abstractos, son más difíciles de nombrar significativamente
jk.
1
@jk, sí, de acuerdo! Al mismo tiempo, es por eso que tienen una curva de aprendizaje empinada para los programadores con antecedentes imperativos y poca matemática (como yo), y por qué valen la pena.
Richard Close
3

Si entendí su último comentario correctamente, su pregunta es ¿por qué Haskell a menudo usa operadores simbólicos en lugares donde también podría usar palabras clave alfanuméricas (o nombres de funciones)?

Con respecto a las palabras clave, una respuesta sería que las palabras clave le impiden usar ciertas palabras como nombres de variables. Por ejemplo, siempre me molesta cuando quiero llamar a mis variables fromy toen un idioma donde una de ellas es una palabra clave, como en Python.

Otra razón para los operadores simbólicos en general es la concisión. Eso realmente no se aplica en sus ejemplos específicos de comprensión de listas ( <-no es más corto que in), pero en muchos casos lo hace.

Otra razón más es la legibilidad. Esto puede parecer contrario a la intuición porque los operadores simbólicos son a menudo más difíciles de aprender ya que sus "nombres" realmente no le dicen nada sobre lo que hacen (mientras que el nombre de una función generalmente lo hará), pero una vez que sabe lo que hace un operador determinado, Las expresiones con operadores simbólicos infijidos son a menudo más fáciles de analizar para un humano que para uno con muchas llamadas de función de prefijo alfanumérico, ya que los operadores se distinguen visualmente más fácilmente de los operandos de esa manera. Por ejemplo, la mayoría de la gente estaría de acuerdo en que 2 * 3 + 4es más fácil de leer que add (mult 2 3) 4o add(mult(2, 3), 4).

sepp2k
fuente
@PeterTaylor No, solo yo soy estúpido ;-) Solucionado ahora.
sepp2k
3

Los lenguajes informáticos imperativos en su mayoría no están más cerca de los lenguajes naturales que, por ejemplo, Haskell.

Sin embargo, algunos están diseñados para parecerse más al inglés: Cobol e Hypercard, por ejemplo. Las lecciones que sacaría de estos ejemplos son:

  • la similitud con los lenguajes naturales no parece producir mejoras directas en la usabilidad
  • emular lenguajes naturales directamente puede producir lenguajes de computadora que son verbosos y oscuros

Según los informes, el lenguaje de computadora Perl fue diseñado con algunos aspectos más sutiles del lenguaje natural en mente . Yo juzgaría que Perl funciona mejor que Cobol o Hypercard en la usabilidad general, pero las personas tienen opiniones diferentes sobre Perl.

tormenta
fuente
3

Creo que Haskell es tan similar al lenguaje humano como uno puede obtener sin introducir una sintaxis loca. Realmente va muy lejos hacia esto, por ejemplo, con la wherecláusula para posponer una definición y con la sintaxis de comprensión de la lista, que es exactamente lo que escribiría en una pizarra. También evita caracteres extraños como llaves y tiene un uso liberal de sangría. El ejemplo típico es quicksort:

qsort [] = []
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
               where lesser = [x | x <- xs, x <= p] 
                     greater = [x | x <- xs, x > p]

Admitido, es un ejemplo simple, pero no conozco ningún otro idioma que lo haga tan legible como este.

Hacer cosas más complicadas puede ser difícil de leer en Haskell, pero eso tiene que ver con el sistema de tipos, el IO restringido y no con la sintaxis.

En todo caso, diría que Haskell ha sacrificado la simplicidad sintáctica para acomodar una sintaxis que es más similar al lenguaje humano. Un esquema similar al lenguaje tiene una sintaxis que está muy lejos de lo que un humano escribiría, pero es realmente simple explicar sus reglas.

Andrea
fuente
3
Apenas lo llamaría legible para los humanos. Yo quicksort. Estoy familiarizado con cómo configurarlo en varios idiomas diferentes, sé lo que se supone que debe hacer, y todavía no puedo sacar cara o cruz de la mitad inferior de ese fragmento de código.
Mason Wheeler
Supongo que realmente depende de tus antecedentes. Esto es tan simple como me parece ...
Andrea
2
En cualquier caso, se supone que se parece a esta notación: purplemath.com/modules/setnotn.htm
Andrea
44
¿Estás seguro de que no debería ser ++ [p] ++?
Peter Taylor
1
@Mason: Me parece bastante claro, y nunca he escrito una línea de Haskell
kevin cline el
2

Creo que la diferencia tiene que ver con la forma en que la programación funcional / declarativa hace declaraciones sobre un problema como si fuera un problema matemático, donde la programación imperativa describe un proceso . En el mundo de los negocios, los programas de computadora envuelven o reemplazan los procesos físicos, por lo que puede encontrar un lenguaje que refleje que esto sea más intuitivo.

Resulta que el estilo funcional se presta para hacer un uso seguro de múltiples procesadores (porque minimiza la mutabilidad y los efectos secundarios), algo que veremos más en el futuro. Además, la mayoría de los lenguajes funcionales modernos tienen colecciones con iteradores a los que puede pasar funciones. Estos métodos pueden dividir su carga de trabajo en múltiples procesadores de manera muy eficiente sin que usted lo sepa.

GlenPeterson
fuente
Creo que esta es la mejor respuesta: la única que aclara la distinción entre proceso y declaraciones.
Milind R