我仍然试图获得函数式编程的思维方式,因此我不确定这个问题是否有意义:F#中的scoping assignment是否可能,因为它在R中?
我想假设split x
x = y + 10z
和abs(int:y) <= 5
时我正在设计一个函数abs(int:z)
。
let split x =
let z = abs(x / 10)
let modz = abs(x % 10)
let y =
if modz > 5 then
let z = z + 1
abs(5 - modz)
else
modz
(y, z);;
假设z的模块大于5,我想修改z的值。
即,对于split 27
我期待结果(2,3)。
split 22;;
val it : int * int = (2, 2)
split 27;;
val it : int * int = (2, 2)
答案 0 :(得分:7)
let
关键字创建名称绑定,这意味着“此名称表示此值”(或此函数)。它是不可变的:在您编写的代码中,z
函数中的名称split
将始终引用值abs(x / 10)
,并且无法更改。 let z = z + 1
块中的if modz > 5 = ...
表达式不会重新分配外部z
的值。相反,它正在创建z
的新定义,它位于其所在的块的本地。您编写的代码是“在{{1}的真实部分内}表达式,我想要一个名为if
的名称,其值是我目前所知道的z
的值,加上1.哦,并隐藏“外部”z
来自我:里面这个块,我想使用我的定义z
。“但在街区之外,“外部”z
没有变化。这允许您随意重新定义名称,而不会在其他代码中意外地导致错误,这通常是一件好事。
您要做的是创建可变变量,并通过将z
关键字添加到mutable
来完成。为可变变量赋值的语法也不同:它根本不使用let
。你想要的是写:
let
左向箭头操作符let mutable z = abs(x / 10)
// Later on...
z <- z + 1
表示“更改此可变变量的值”。如果你写<-
,这是一个常见的新手错误,编译器会给你一个警告,这是一个被忽略的布尔值 - 因为当它不是z = z + 1
绑定的一部分时,{ {1}}运算符是比较。表达式let
询问“=
是否等于z = z + 1
?”这将永远是假的(除非你创建了一个非常奇怪的数字类型)。
我不建议使用z
作为一般规则。尝试重写您的逻辑以避免它。例如,您可以像这样编写函数:
z + 1
这将更具功能性,并避免使用mutable
。
答案 1 :(得分:4)
在F#中,值(变量)是不可变的,你不能更新z的值。
let z = abs(x / 10)
并且
let z = z + 1
是不同的声明值,具有不同的范围。
F#中的范围由缩进标识,因此当您返回时
(y, z);;
使用相同的缩进(let z = abs(x / 10)
)