我的程序有以下全局变量:
let a = (0.0,0.0);;
以下,eval e1
返回string_of_float,somefunc e2
返回元组。
let rec output_expr = function
Binop(e1, op, e2) ->
let onDist = float_of_string(eval e1) and onDir = somefunc e2 in
let newA = onDir in (
fprintf oc "\n\t%s" ("blah");
fprintf oc "\n\t%s" ("blah");
fprintf oc "\n\t%s" ("blah");
let a = newA
)
现在,上面的代码给出了以下错误:
Error: This expression has type bool but an expression was expected of type unit Command exited with code 2.
我希望let a = newA
更改全局变量a
的值。我怎么能这样做?
答案 0 :(得分:3)
要做到这一点,你需要将值作为参考,
let a = ref (0.0, 0.0)
然后该状态可以改变,
a := (1.0, 2.0);
在功能性世界中,你不希望拥有这种全球状态。有时它非常有用,但在这种特殊情况下是值得怀疑的。您应该将值a
传递给函数并返回可以在以后使用的新值(a'
);请注意,该值永远不会更改,但新值将取代并用于进一步计算。
在您的特定情况下,我认为您需要问问自己为什么名为output_expr
的函数会修改某个全局状态,或返回除unit
之外的任何内容。但也许这是我们消费的一个玩具示例,所以我会留下它。
答案 1 :(得分:3)
您无法在OCaml中分配变量(本地或全局相同)。语言中根本就没有语法。换句话说,OCaml中的变量是其他语言所谓的“常量” - 它们在初始化时获得一次值,就是这样。
但是,您可以使用可变数据结构,该结构提供了修改其内容的方法。数据结构是引用类型,您可以在变量中保存对数据结构的引用,并修改内容,而无需分配给变量。
nlucaroni提到了这样一个数据结构ref
,它是一个包含所需类型值的简单可变单元格。还有其他可变数据结构,如数组,字符串和任何带有mutable
字段的记录。每种方法都有自己修改内容的方式。
但是,在函数式编程中大多可以避免使用可变状态,如果依赖于可变状态,则可能表明您没有以功能方式执行此操作。
答案 2 :(得分:2)
在OCaml中,值是不可变的。您无法更改值的内容,应重新组织代码,以便您不需要。
在这里,您的函数output_expr
应该返回newA
,之后应该使用此值而不是a
。
实际上你可以使用引用来获取可变变量,但是如果你知道你做了什么并且认为它们更适合某个特定用例,那么你应该只使用它们,绝不会因为你不理解不变性。