Lucid es un lenguaje de programación de flujo de datos diseñado para experimentar con modelos de programación distintos al de von Neumann . Fue diseñado por Bill Wadge y Ed Ashcroft y descrito en el libro de 1985 Lucid, the Dataflow Programming Language . [ 1 ]
pLucid fue el primer intérprete de Lucid.
Modelo
Lucid utiliza un modelo basado en la demanda para el procesamiento de datos. Cada instrucción puede entenderse como una ecuación que define una red de procesadores y líneas de comunicación entre ellos, a través de las cuales fluyen los datos. Cada variable es un flujo infinito de valores y cada función es un filtro o un transformador. La iteración se simula mediante valores actuales y el operador "fby" (seguido de), que permite la composición de flujos.
Lucid se basa en un álgebra de historiales, donde un historial es una secuencia infinita de datos. Operacionalmente, un historial puede entenderse como un registro de los cambios en los valores de una variable; las operaciones de historial, como `first` y `next`, se comprenden según lo sugieren sus nombres. Lucid se concibió originalmente como un lenguaje disciplinado, matemáticamente puro y de asignación única, en el que la verificación se simplificaría. Sin embargo, la interpretación del flujo de datos ha influido significativamente en la evolución de Lucid.
Detalles
En Lucid (y otros lenguajes de flujo de datos ), una expresión que contiene una variable que aún no se ha vinculado espera hasta que se haya vinculado antes de continuar. Una expresión como esta x + yesperará hasta que tanto x como y estén vinculadas antes de devolver el resultado. Una consecuencia importante de esto es que se evita la lógica explícita para actualizar valores relacionados, lo que resulta en una reducción sustancial del código en comparación con los lenguajes convencionales.
En Lucid, cada variable es una secuencia de valores. Una expresión n = 1 fby n + 1define una secuencia mediante el operador 'fby' (un acrónimo de "seguido de"). fby define lo que sigue a la expresión anterior. (En este caso, la secuencia produce 1, 2, 3, ...). Los valores de una secuencia se pueden acceder mediante estos operadores (suponiendo que x es la variable que se está utilizando):
first x- obtiene el primer valor en el flujo x,
x- el valor actual del flujo,
next x- Obtiene el siguiente valor en el flujo.
asa- un operador que realiza alguna acción "tan pronto como" se cumple la condición dada.
x upon p- El operador `onup` repite el valor anterior del flujo `x` y lo actualiza solo cuando el flujo `p` proporciona un
truevalor. (Su función es ralentizar el flujo `x`).
es decir: x upon p¿es el flujo x con nuevos valores que aparecen sobre la verdad de p?
El cálculo se lleva a cabo definiendo filtros o funciones de transformación que actúan sobre estos flujos de datos variables en el tiempo.
Ejemplos
Factorial
fac dónde n = 0 fby (n + 1); fac = 1 fby ( fac * (n + 1) ); fin secuencia de Fibonacci
mentira dónde fib = 0 fby ( 1 fby fib + siguiente fib ); fin Total de una secuencia
total dónde total = 0 fby total + x fin; promedio móvil
promedio de carrera dónde suma = first(input) fby suma + next(input); n = 1 fby n + 1; promedio_de_carrera = suma / n; fin; Números primos
principal dónde primo = 2 fby (n siempre que [[esprimo]](n)); n = 3 fby n+1; esprimo(n) = no(divs) como divs o primo*primo > N dónde N es el n actual; divs = N mod primo igual a 0; fin; fin Diagrama de flujo de datos

Ordenación rápida
qsort(a) = si eof(primer a) entonces a sino seguir(qsort(b0),qsort(b1)) fi donde p = primero a < a; b0 = a siempre que p; b1 = a siempre que no sea p; seguir(x,y) = si xhecho entonces y cuando xhecho sino x fi dónde xdone = iseod x fby xdone o iseod x; fin fin Diagrama de flujo de datos
--------> siempre que -----> qsort --------- | ^ | | | | | no | | ^ | |---> primero | | | | | | | V | | |---> menos --- | | | | | VV ---+--------> siempre que -----> qsort -----> conc -------> ifthenelse -----> | ^ ^ | | | --------> siguiente ----> primero ------> iseod -------------- | | | ----------------------------------------------------------- raíz cuadrática media
raíz cuadrada(promedio(cuadrado(a))) dónde cuadrado(x) = x*x; promedio(y) = media dónde n = 1 fby n+1; media = primera y fby media + d; d = (siguiente y - media)/(n+1); fin; raíz cuadrada(z) = aproximadamente err < 0,0001 dónde Z es la z actual; aprox = Z/2 fby (aprox + Z/aprox)/2; err = abs(cuadrado(aprox.)-Z); fin; fin problema de Hamming
h dónde h = 1 fby merge(merge(2 * h, 3 * h), 5 * h); fusionar(x,y) = si xx <= yy entonces xx sino yy fi dónde xx = x cuando xx <= yy; yy = y sobre yy <= xx; fin; fin; Diagrama de flujo de datos

Intensionalidad y lúcido
Desde la perspectiva de la lógica intensional [ 2 ] , Lucid puede considerarse un lenguaje de programación multidimensional [ 3 ] , donde el tiempo es una de sus múltiples dimensiones. Visto de esta manera, Lucid puede expresar de forma natural computaciones multidimensionales que varían no solo en el tiempo, sino también en otras dimensiones [ 4 ] . Los ejemplos que se presentan a continuación ilustran el potencial de Lucid para expresar una amplia gama de computaciones multidimensionales.
Números primos
primos donde dimensión i; primos = primer.i tamiz; natsFrom2 = i+2; tamiz = natsFrom2 fby.time ( tamiz wvr.i ( tamiz mod ( ( primer.i tamiz ) ne 0 ) ) ); fin Ordenación por fusión
r0t8.v,tiempo(salida) dónde dimensión v,h,t; salida = mergeSort asa.t inputSize == sizeOfMerge; fusionar(x,y) = si iseod xx entonces yy de lo contrario, si iseod yy entonces xx si no, si xx <= yy entonces xx si no yy fi fi fi dónde xx = x upon.v iseod yy || xx <= yy; yy = x upon.v iseod xx || xx > yy; fin; mergeSort = Inputdata(h) fby.t fusionar(hijoizquierdo.h(mergeSort), hijoderecho.h(mergeSort)); sizeOfMerge = 1 fby.t 2*sizeOfMerge; r0t8.a,b( x ) = x @.ab; fin Multiplicación de matrices
(matmult(A, B, n) @.aux_i r) @.aux_j c donde dimensión aux_i, aux_j; matmult( aux_a, aux_b, n ) = c asa.ts == (n*n*n) donde dimensión t, i, j, k; s = 1 fby.t 8*s; d = 1 fby.t 2*d; a = r0t8.aux_i.i( r0t8.aux_j.j( aux_a ) ); b = r0t8.aux_i.i( r0t8.aux_j.j( aux_b ) ); c = (a @.jk) * (b @.ik) fby.t ( ( reducir @.k (2*k) ) @.j (2*j) ) @.i (2*i) donde reducir = bloque( c + next.kc, next.jc + next.k next.jc, next.ic + next.k next.ic, siguiente.j siguiente.ic + siguiente.k siguiente.j siguiente.ic, d ); bloque( tl, tr, bl, br, d ) = p donde p = agregar.aux_i( agregar.aux_j(tl, tr, d), append.aux_j( bl, br, d ), d ); append.dim( a, b, d ) = if( dim < d ) then a de lo contrario b @.dim (dim-d) fi; fin; fin; r0t8.ab( x ) = x @.ab; fin; fin Referencias
- ↑ Wadge, William W.; Ashcroft, Edward A. (1985). Lucid, el lenguaje de programación de flujo de datos . Academic Press. ISBN 0-12-729650-6Consultado el 8 de enero de 2015 .
- ↑ Orgun, Mehmet; Wadge, William (1992). "Hacia una teoría unificada de la programación lógica intensional" . The Journal of Logic Programming . 13 (4): 413– 440. doi : 10.1016/0743-1066(92)90055-8 . ISSN 0743-1066 .
- ^ Ashcroft, EA; Faustini, AA; Jagannathan, R.; Wadge, WW (23 de febrero de 1995). Programación multidimensional . Prensa de la Universidad de Oxford. ISBN 978-0-19-536045-5.
- ↑ "Resolución de problemas multidimensionales en Lucid" . www.csl.sri.com . Consultado el 9 de abril de 2026 .
Enlaces externos
- Sitio web oficial , pLucid
- Lenguajes de programación académica
- Lenguajes de programación concurrentes
- lenguajes de programación declarativos
- Lenguajes de programación experimentales
- Lenguajes de programación reactivos
- Lenguajes de consulta