首页 > 其他 > 详细

F#: mutable 关键字不适宜用于结构中声明可变值

时间:2014-08-17 18:24:42      阅读:279      评论:0      收藏:0      [点我收藏+]
 关于之前日志F#编译器的一个Bug》,有一个问题,Set函数既然运行正常,改变的值去哪里了?以下例子做出了解答:
 
[<Struct>]

type TestStruct =

    val mutable _x: int

    new(x) = {_x = x}

    member this.Set(x) =

        this._x <- x

        this

member this.X with get() = this._x;

 

let a = TestStruct(2)

let c() =

    let b = a.Set 10

    b.X

c();;

 
代码运行结果为10(我们想要的结果)。众所周知,类的子函数,其背后的实现是一个带对象输入的公共函数,调用a.Set(x),等效于执行伪代码:

Set(a, x) 。

由此可见,当我们绑定 
let a = TestStruct(2),调用a.Set(x) 的时候,传递到Set函数中的this,其实是个复制值。
而当
我们绑定 let mutable a = TestStruct(2),调用a.Set(x) 的时候,传递到Set函数中的this,却是a本身。

 
虽然,当我们在结构中使用
mutable 的时候,可以使用返回this的方式,返回一个新的结构值。这也很符合函数编程的规范。但是如果可变数值使
用的是引用单元格,而不是
mutable 的话。表现又略微不同:

 
mutable 方式,a值和Set返回值不同,一个表示原始值,另一个表示修改后的值;

引用单元格方式,a就是修改后的值。

[<Struct>]

type TestStruct =

    val _x: int ref

    new(x) = {_x = ref x}

    member this.Set(x) =

        this._x := x

member this.X with get() = !this._x; 

let a = TestStruct(2)

let c() =

    a.Set 10

    a.X

 

c();;

以上这段代码,可以得到正确值10,原理很简单,int ref实际上是一个类,所以结构复制后,其对应的对象都是同一个。 
 

所以用户仍然无法从习惯风格本身理解 
TestStruct.Set(x)函数的行为。此外.Net库里面常用的一个StringBiulder类,它的行为特征,则完全符合引用单元格方式。所以结构中,mutable 的使用要尤其审慎。毕竟,一个结构,如果let绑定使用和let mutable绑定使用,两者之间行为不一致的话,利用这种特性写出的代码,未免太奇淫技巧一点,徒增读代码的难度。


F#: mutable 关键字不适宜用于结构中声明可变值,布布扣,bubuko.com

F#: mutable 关键字不适宜用于结构中声明可变值

原文:http://www.cnblogs.com/greatim/p/3917991.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!