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