范围分配

Wor*_*ice 3 f#

我仍然试图获得函数式编程的思维方式,因此我不确定这个问题是否有意义:是否可以在F#中进行作用域分配,因为它在R中?

让我们假设我设计一个功能split x时,x = y + 10zabs(int:y) <= 5abs(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)

rmu*_*unn 7

所述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.