programming languages - Explícame los lenguajes concatenativos como si yo fuera un niño de 8 años.
programming-languages concatenative-language (7)
A su simple pregunta, aquí hay una respuesta subjetiva y argumentativa.
Miré el artículo y varias páginas web relacionadas. Las páginas web dicen que no hay una teoría real, por lo que no es de extrañar que a las personas les resulte difícil encontrar una definición precisa y comprensible. Yo diría que en la actualidad, no es útil clasificar las lenguas como "concatenativas" o "no concatenativas".
A mí me parece un término que le da a Manfred von Thun un lugar para colgar su sombrero, pero puede que no sea útil para otros programadores.
Aunque vale la pena estudiar PostScript y Forth, no veo nada terriblemente nuevo o interesante en el lenguaje de programación Joy de Manfred von Thun. De hecho, si lees el artículo de Chris Okasaki sobre Técnicas para incrustar idiomas de Postfix en Haskell , puedes probar todo esto en un entorno que, en relación con Joy, es totalmente convencional.
Entonces, mi respuesta es que no hay una explicación simple porque no hay una teoría madura que sustente la idea de un lenguaje concatenativo. (Como Einstein y Feynman dijeron, si no puede explicar su idea a un estudiante de primer año de la universidad, no lo entiende realmente). Iré más lejos y diré que estudiar algunos de estos idiomas, como Forth y PostScript, es una excelente uso del tiempo, tratar de averiguar exactamente lo que quiere decir la gente cuando dice "concatenativo" es probablemente una pérdida de tiempo.
He leído el artículo de Wikipedia sobre lenguajes concatenativos , y ahora estoy más confundido que cuando comencé. :-)
¿Qué es un lenguaje concatenativo en términos de personas estúpidas?
Considero que la idea principal es 1. Podemos crear nuevos programas simplemente uniéndonos a otros programas.
Además, 2. Cualquier parte aleatoria del programa es una función válida (o subprograma).
Good old pure RPN Forth tiene esas propiedades, excluyendo cualquier sintaxis aleatoria que no sea RPN.
En el programa 1 2 + 3 *, el subprograma + 3 * toma 2 argumentos y da 1 resultado. El subprograma 2 toma 0 argumentos y devuelve 1 resultado. Cualquier parte es una función, y eso es bueno!
Puede crear nuevas funciones agrupando dos o más otras juntas, opcionalmente con un poco de pegamento. ¡Funcionará mejor si los tipos coinciden!
Estas ideas son realmente buenas, valoramos la simplicidad.
No se limita al lenguaje serial RPN Forth, ni a la programación imperativa o funcional. Las dos ideas también funcionan para un lenguaje gráfico, donde las unidades de programa pueden ser, por ejemplo, funciones, procedimientos, relaciones o procesos.
En una red de procesos de comunicación, cada subred puede actuar como un proceso.
En una gráfica de relaciones matemáticas, cada sub-gráfica es una relación válida.
Estas estructuras son "concatenativas", podemos separarlas de cualquier manera (dibujar círculos) y unirlas de muchas maneras (dibujar líneas).
Bueno, así es como lo veo. Estoy seguro de que me he perdido muchas otras buenas ideas del campamento concatenativo. Si bien estoy interesado en la programación gráfica, soy nuevo en este enfoque sobre la concatenación.
Después de leer http://concatenative.org/wiki/view/Concatenative%20language y dibujar en lo poco que recuerdo de jugar con Forth cuando era adolescente, creo que la clave de la programación concatenativa tiene que ver con:
- Ver datos en términos de valores en una pila de datos específica
- y funciones que manipulan cosas en términos de valores de popping / push en la misma pila de datos
Echa un vistazo a estas citas de la página web anterior:
Hay dos términos que se tiran alrededor, el lenguaje de pila y el lenguaje concatenativo. Ambos definen clases de idiomas similares pero no iguales. En su mayor parte, sin embargo, son idénticos.
La mayoría de los lenguajes de uso generalizado en la actualidad son lenguajes aplicativos: la construcción central en el lenguaje es alguna forma de llamada de función, donde una función se aplica a un conjunto de parámetros, donde cada parámetro es en sí mismo el resultado de una llamada de función, el nombre de un Variable, o una constante. En los lenguajes de pila, una llamada de función se realiza simplemente escribiendo el nombre de la función; los parámetros son implícitos y deben estar ya en la pila cuando se realiza la llamada. El resultado de la llamada a la función (si existe) se deja en la pila después de que la función retorna, para que la siguiente función consuma, y así sucesivamente. Debido a que las funciones se invocan simplemente al mencionar su nombre sin ninguna sintaxis adicional, Forth y Factor se refieren a las funciones como "palabras", porque en la sintaxis realmente son solo palabras.
Esto contrasta con los lenguajes aplicativos que aplican sus funciones directamente a variables específicas.
Ejemplo: sumar dos números.
Lenguaje aplicativo :
int foo(int a, int b)
{
return a + b;
}
var c = 4;
var d = 3;
var g = foo(c,d);
Lenguaje concatenativo (lo inventé, se supone que es similar a Forth ...;))
push 4
push 3
+
pop
Si bien no creo que el lenguaje concatenativo = lenguaje de pila, como los autores señalan anteriormente, parece similar.
En los lenguajes de programación normales, tiene variables que pueden definirse libremente y llama a los métodos que usan estas variables como argumentos. Estos son simples de entender pero algo limitados. A menudo, es difícil reutilizar un método existente porque simplemente no puede asignar las variables existentes a los parámetros que el método necesita o el método A llama a otro método B y A sería perfecto para usted si solo pudiera reemplazar la llamada a B con una llamada a C.
El lenguaje concatenativo usa una estructura de datos fija para guardar valores (generalmente una pila o una lista). No hay variables. Esto significa que muchos métodos y funciones tienen la misma "API": funcionan en algo que otra persona dejó en la pila. Se considera que el código Plus en sí es "datos", es decir, es común escribir código que puede modificarse o que acepta otro código como "parámetro" (es decir, como un elemento en la pila).
Estos atributos hacen que estos idiomas sean perfectos para encadenar código existente para crear algo nuevo. La reutilización está incorporada. Puede escribir una función que acepte una lista y un fragmento de código y llame al código para cada elemento de la lista. Ahora funcionará con cualquier tipo de datos siempre que se comporte como una lista: resultados de una base de datos, una fila de píxeles de una imagen, caracteres en una cadena, etc.
El mayor problema es que no tienes ninguna pista de lo que está pasando. Solo hay un par de tipos de datos (lista, cadena, número), por lo que todo se asigna a eso. Cuando obtiene un dato, por lo general no le importa qué es o de dónde proviene. Pero eso hace que sea difícil seguir los datos a través del código para ver qué le está sucediendo.
Creo que se necesita una cierta mentalidad para usar los idiomas con éxito. Ellos no son para todos.
[EDITAR] Forth tiene algo de penetración pero no tanto. Puedes encontrar PostScript en cualquier impresora láser moderna. Así que son lenguajes de nicho.
Desde un nivel funcional, están a la par con LISP, lenguajes tipo C y SQL: todos ellos son Turing Complete , por lo que puede calcular cualquier cosa. Es solo una cuestión de cuánto código tienes que escribir. Algunas cosas son más simples en LISP, algunas son más simples en C, algunas son más simples en los lenguajes de consulta. La pregunta que es "mejor" es inútil a menos que tenga un contexto.
Mi definición pragmática (y subjetiva) para programación concatenativa (ahora, puedes evitar leer el resto):
-> composición de funciones en formas extremas (con sintaxis RPN):
( Forth code )
: fib
dup 2 <= if
drop 1
else
dup 1 - recurse
swap 2 - recurse +
then ;
-> todo es una función, o al menos, puede ser una función:
( Forth code )
: 1 1 ; / define a function 1 to push the literal number 1 on stack
-> los argumentos se pasan implícitamente sobre las funciones (ok, parece ser una definición para programación tácita), pero esto en Forth:
a b c
Puede estar en Lisp:
(c a b)
(c (b a))
(c (b (a)))
entonces, es fácil generar código ambiguo ... puede escribir definiciones que empujan el xt (token de ejecución) en la pila y definir un pequeño alias para ''ejecutar'':
( Forth code )
: <- execute ; / apply function
así, obtendrá:
a b c <- / Lisp: (c a b)
a b <- c <- / Lisp: (c (b a))
a <- b <- c <- / Lisp: (c (b (a)))
No puedes explicar un idioma, solo obtén uno ( Factor , preferiblemente) y prueba algunos tutoriales . Los tutoriales son mejores que las respuestas de desbordamiento de pila.
Primero voy a hacer una refutación a la afirmación de Norman Ramsey de que no hay teoría.
Teoría de los lenguajes concatenativos
Un lenguaje concatenativo es un lenguaje de programación funcional, donde la operación predeterminada (lo que sucede cuando dos términos están lado a lado) es la composición de la función en lugar de la aplicación de la función. Es tan simple como eso.
Entonces, por ejemplo, en el Cálculo del Combinador de SKI (uno de los lenguajes funcionales más simples), dos términos de lado a lado son equivalentes a aplicar el primer término al segundo término. Por ejemplo: SKK
es equivalente a S(K)(K)
.
En un lenguaje concatenativo, SKK
sería equivalente a S . K . K
S . K . K
S . K . K
en Haskell.
Así que cuál es el problema
Un lenguaje concatenativo puro tiene la propiedad interesante de que el orden de evaluación de los términos no importa. En un lenguaje concatenativo (SK) K
es lo mismo que S (KK)
. Esto no se aplica a SKI Calculus ni a ningún otro lenguaje de programación funcional basado en la aplicación de funciones.
Una razón por la que esta observación es interesante porque revela oportunidades para la paralelización en la evaluación del código expresado en términos de composición de funciones en lugar de aplicación.
Ahora para el mundo real
La semántica de los lenguajes basados en pila que admiten funciones de orden superior puede explicarse mediante un cálculo concatenativo. Simplemente asigna cada término (comando / expresión / subprograma) para que sea una función que toma una función como entrada y devuelve una función como salida. Todo el programa es efectivamente una función de transformación de pila única.
La realidad es que las cosas siempre están distorsionadas en el mundo real (por ejemplo, FORTH tiene un diccionario global, PostScript hace cosas extrañas cuando el orden de evaluación es importante). La mayoría de los lenguajes de programación prácticos no se adhieren perfectamente a un modelo teórico.
Ultimas palabras
No creo que un programador típico o un niño de 8 años deba preocuparse por lo que es un lenguaje concatenativo. Tampoco me parece particularmente útil para los lenguajes de programación de casilleros como tipo X o tipo Y.