范围分配

时间:2016-10-24 10:01:02

标签: f#

我仍然试图获得函数式编程的思维方式,因此我不确定这个问题是否有意义:F#中的scoping assignment是否可能,因为它在R中?

我想假设split x x = y + 10zabs(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)

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)

返回z