programming languages - science - ¿Verdaderamente lenguaje declarativo?
programing languages paradigms (19)
¿Has visto Resolver One ? Es como Excel con un lenguaje de programación real detrás de él.
¿Alguien sabe de un lenguaje verdaderamente declarativo? El comportamiento que busco es el tipo de Excel que hace, donde puedo definir variables y fórmulas, y el resultado de la fórmula cambia cuando cambia la entrada (sin haber configurado la respuesta otra vez)
El comportamiento que estoy buscando se muestra mejor con este pseudo código:
X = 10 // define and assign two variables
Y = 20;
Z = X + Y // declare a formula that uses these two variables
X = 50 // change one of the input variables
?Z // asking for Z should now give 70 (50 + 20)
He intentado esto en muchos lenguajes como F #, python, matlab, etc., pero cada vez que lo intento, aparecen 30 en lugar de 70. Lo que es correcto desde un punto de vista imperativo, pero estoy buscando un Comportamiento más declerativo si sabes a qué me refiero.
Y esto es sólo un cálculo muy simple. Cuando las cosas se ponen más difíciles, debería manejar cosas como la recursión y la memorización de forma automática.
El código a continuación obviamente funcionaría en C # pero es solo un código para el trabajo, estoy buscando algo más al punto sin todo ese ''ruido técnico''
class BlaBla{
public int X {get;set;} // this used to be even worse before 3.0
public int Y {get;set;}
public int Z {get{return X + Y;}}
}
static void main(){
BlaBla bla = new BlaBla();
bla.X = 10;
bla.Y = 20;
// can''t define anything here
bla.X = 50; // bit pointless here but I''ll do it anyway.
Console.Writeline(bla.Z);// 70, hurray!
}
Esto parece mucho código, llaves y punto y coma que no agregan nada.
¿Hay un idioma / aplicación (aparte de Exel) que hace esto? Tal vez no lo estoy haciendo bien en los idiomas mencionados, o me he perdido por completo una aplicación que hace precisamente esto.
Prototipé un lenguaje / aplicación que hace esto (junto con algunas otras cosas) y estoy pensando en producirlo. Simplemente no puedo creer que todavía no haya llegado. No quiero perder mi tiempo.
Aquí está el ejemplo de Daniel en Python, ya que noté que dijiste que lo intentaste en Python.
x = 10
y = 10
z = lambda: x + y
# Output: 20
print z()
x = 20
# Output: 30
print z()
Cualquier sistema de Programación de Restricciones lo hará por usted. Ejemplos de sistemas de CP que tienen un idioma asociado son ECLiPSe , paquete de Prolog / CP de SICSTUS, Comet, MiniZinc, ...
En F #, un poco verbalmente:
let x = ref 10
let y = ref 20
let z () = !x + !y
z();;
y <- 40
z();;
En Mathematica, puedes hacer esto:
x = 10; (* # assign 30 to the variable x *)
y = 20; (* # assign 20 to the variable y *)
z := x + y; (* # assign the expression x+y to the variable z *)
Print[z];
(* # prints 30 *)
x = 50;
Print[z];
(* # prints 70 *)
El operador :=
(SetDelayed) es diferente de =
(Set). El primero enlaza una expresión no evaluada a una variable, el último enlaza una expresión evaluada .
Este código F # debería hacer el truco. Puede usar la evaluación perezosa (objeto System.Lazy) para asegurarse de que su expresión se evaluará cuando sea realmente necesaria, no antes.
let mutable x = 10;
let y = 20;
let z = lazy (x + y);
x <- 30;
printf "%d" z.Value
Groovy y la magia de los cierres.
def (x, y) = [ 10, 20 ]
def z = { x + y }
assert 30 == z()
x = 50
assert 70 == z()
def f = { n -> n + 1 } // define another closure
def g = { x + f(x) } // ref that closure in another
assert 101 == g() // x=50, x + (x + 1)
f = { n -> n + 5 } // redefine f()
assert 105 == g() // x=50, x + (x + 5)
También es posible agregar memoización automágica a las funciones, pero es mucho más complejo que solo una o dos líneas. http://blog.dinkla.net/?p=10
Hay una biblioteca Lisp con este tipo de comportamiento:
JavaFX lo hará por usted si usa bind
lugar de =
para Z
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
x = 10
y = 20
z = función () devuelve x + y; fin
x = 50
= z ()
70
No es lo que está buscando, pero los lenguajes de descripción de hardware son, por definición, "declarativos".
No estoy seguro de qué tan bien funcionaría metapost ( 1 ) para su aplicación, pero es declarativo.
Parece que solo quieres hacer que Z almacene una función en lugar de un valor. Cía#:
var X = 10; // define and assign two variables
var Y = 20;
Func<int> Z = () => X + Y; // declare a formula that uses these two variables
Console.WriteLine(Z());
X = 50; // change one of the input variables
Console.WriteLine(Z());
Entonces, ¿el equivalente a tu ?
La sintaxis de prefijo es un ()
-suffix, pero por lo demás es idéntica. Un lambda es una "fórmula" en su terminología.
Detrás de escena, el compilador de C # construye casi exactamente lo que presentó en su ejemplo conceptual de C #: convierte a X
en un campo en una clase generada por compilador, y asigna una instancia de esa clase cuando se ingresa el bloque de código. Así que felicidades, has re-descubierto lambdas! :)
Puede encontrar este video (del sitio web de Usuarios Comerciales de Programación Funcional ) interesante y que vale la pena ver. Si tienes usuarios bastante tecnofóbicos, este puede ser un buen enfoque para ti.
Puedes hacer esto en Tcl, un poco. En tcl puede establecer una traza en una variable de modo que cada vez que se acceda a ella se pueda invocar un procedimiento. Ese procedimiento puede recalcular el valor sobre la marcha.
A continuación se muestra un ejemplo de trabajo que hace más o menos lo que pides:
proc main {} {
set x 10
set y 20
define z {$x + $y}
puts "z (x=$x): $z"
set x 50
puts "z (x=$x): $z"
}
proc define {name formula} {
global cache
set cache($name) $formula
uplevel trace add variable $name read compute
}
proc compute {name _ op} {
global cache
upvar $name var
if {[info exists cache($name)]} {
set expr $cache($name)
} else {
set expr $var
}
set var [uplevel expr $expr]
}
main
Puedes imitarlo en Ruby:
x = 10
y = 20
z = lambda { x + y }
z.call # => 30
z = 50
z.call # => 70
No es exactamente lo mismo que quieres, pero está bastante cerca.
Querer tener dos definiciones de X es inherentemente imperativo . En un lenguaje verdaderamente declarativo, tiene una sola definición de una variable en un solo ámbito. El comportamiento que desea de Excel corresponde a la edición del programa.
react es una biblioteca OCaml frp. Al contrario de las emulaciones ingenuas con cierres, volverá a calcular los valores solo cuando sea necesario.
Objective Caml version 3.11.2
# #use "topfind";;
# #require "react";;
# open React;;
# let (x,setx) = S.create 10;;
val x : int React.signal = <abstr>
val setx : int -> unit = <fun>
# let (y,sety) = S.create 20;;
val y : int React.signal = <abstr>
val sety : int -> unit = <fun>
# let z = S.Int.(+) x y;;
val z : int React.signal = <abstr>
# S.value z;;
- : int = 30
# setx 50;;
- : unit = ()
# S.value z;;
- : int = 70