有谁知道真正的声明性语言?我正在寻找的行为类似于Excel所做的事情,我可以在其中定义变量和公式,并在输入发生变化时更改公式的结果(没有自己再次设置答案)
我正在寻找的行为最好用这个伪代码显示:
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)
我已经尝试过很多语言,如F#,python,matlab等,但每次尝试这个时,他们都会提出30而不是70.从命令的角度来看,这是正确的,但我是如果你知道我的意思,寻找一个更加充满期待的行为。
这只是一个非常简单的计算。当事情变得更加困难时,它应该自动处理递归和记忆等事情。
下面的代码显然可以在C#中运行,但它只是为了这份工作的代码,我正在寻找更多的东西,而没有那些'技术噪音'
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!
}
这看起来像是如此多的代码,花括号和分号,什么也没有添加。
是否有语言/应用程序(Exel除外)这样做?也许我在上面提到的语言中没有做到这一点,或者我完全错过了这样做的应用程序。
我制作了一个语言/应用程序原型(以及其他一些东西)并且正在考虑将其产品化。我简直不敢相信它还没有。不想浪费我的时间。
答案 0 :(得分:17)
任何Constraint Programming系统都会为您做到这一点。 具有相关语言的CP系统的示例是ECLiPSe,SICSTUS Prolog / CP包,Comet,MiniZinc,......
答案 1 :(得分:15)
看起来你只想让Z存储一个函数而不是一个值。在C#中:
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());
因此,?
- 前缀语法的等价物是()
- 后缀,但是它是相同的。 lambda是你术语中的“公式”。
在幕后,C#编译器几乎完全构建了您在C#概念示例中提供的内容:它将X
放入编译器生成的类中的字段中,并在代码块中分配该类的实例进入。所以恭喜你,你重新发现了lambdas! :)
答案 2 :(得分:9)
在Mathematica中,您可以这样做:
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 *)
运算符:=
(SetDelayed)与=
(Set)不同。前者将未评估的表达式绑定到变量,后者绑定评估的表达式。
答案 3 :(得分:5)
希望有两个X定义是固有的命令式。在真正的声明性语言中,您可以在单个范围内对变量进行单一定义。您希望从Excel中执行的操作对应于编辑程序。
答案 4 :(得分:3)
你见过Resolver One吗?它就像Excel背后有一种真正的编程语言。
答案 5 :(得分:3)
这是Daniel在Python中的例子,因为我注意到你说你在Python中尝试过它。
x = 10
y = 10
z = lambda: x + y
# Output: 20
print z()
x = 20
# Output: 30
print z()
答案 6 :(得分:2)
答案 7 :(得分:2)
react是一个OCaml frp库。与具有闭包的天真模拟相反,它仅在需要时重新计算值
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
答案 8 :(得分:2)
如果您使用bind
代替=
来支持Z
答案 9 :(得分:2)
有一种具有这种行为的Lisp库:
答案 10 :(得分:1)
你可以在Tcl中做一些。在tcl中,您可以在变量上设置跟踪,以便无论何时访问它,都可以调用过程。该程序可以动态重新计算该值。
以下是一个可以或多或少地提出要求的工作示例:
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
答案 11 :(得分:0)
Groovy和闭包的魔力。
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)
也可以为函数添加自动记忆,但它比一两行更复杂。 http://blog.dinkla.net/?p=10
答案 12 :(得分:0)
在F#中,有点啰嗦:
let x = ref 10
let y = ref 20
let z () = !x + !y
z();;
y <- 40
z();;
答案 13 :(得分:0)
你可以在Ruby中模仿它:
x = 10
y = 20
z = lambda { x + y }
z.call # => 30
z = 50
z.call # => 70
不完全与你想要的相同,但非常接近。
答案 14 :(得分:0)
您可能会发现this video(来自Commercial Users of Functional Programming网站)有趣且值得一看。如果你有漂亮的技术恐惧症用户,这可能是一个很好的方法。
答案 15 :(得分:0)
不确定metapost(1)对您的应用程序有多好,但它是声明性的。
答案 16 :(得分:0)
Lua 5.1.4版权所有(C)1994-2008 Lua.org,PUC-Rio
x = 10
y = 20
z = function()返回x + y;结束
x = 50
= z()
70
答案 17 :(得分:-1)
这不是您要找的东西,但根据定义,硬件描述语言是“声明性的”。
答案 18 :(得分:-1)
这个F#代码应该可以解决问题。您可以使用延迟评估(System.Lazy对象)来确保在实际需要时评估表达式,而不是更快。
let mutable x = 10;
let y = 20;
let z = lazy (x + y);
x <- 30;
printf "%d" z.Value