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

关于之前日志《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 关键字不适宜用于结构中声明可变值

时间: 2024-12-07 12:15:27

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

深入理解C 中的mutable关键字

mutalbe的中文意思是“可变的,易变的”,跟constant(既C 中的const)是反义词. 在C 中,mutable也是为了突破const的限制而配置的.被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中. 我们知道,假如类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的.但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰. 下面是个小例子: class ClxTest

C++ 中的 mutable 关键字

C++ 中的 mutable 关键字 在C++中,mutable 是为了突破 const 的限制而设置的.可以用来修饰一个类的成员变量.被 mutable 修饰的变量,将永远处于可变的状态,即使是 const 函数中也可以改变这个变量的值. 比如下面这个例子: #include <iostream> using namespace std; class Test { public: Test(); int value() const; private: mutable int v; }; Te

C++要点(1)mutable关键字

mutable语义 const语义 mutable和const的关系 mutable提供的灵活性 mutable语义 在C++中,mutable是为了突破const的限制而设置的. 被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中,甚至结构体变量或者类对象为const,其mutable成员也可以被修改. 例如: #include <iostream> class Tester { public: Tester(int x, int y) : a_normal(x),

mutable关键字

mutable 用法  mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词. 在C++中,mutable也是为了突破const的限制而设置的.被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中. 我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的.但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰. 下面是一个小例子

mutable 关键字

mutable 在C++中,mutable修饰成员变量也是为了突破const的限制而设置的.被mutable修饰的成员变量,将永远处于可变的状态,即使在一个const函数中. class a { mutable int a; int ab(int a) const; } 解释: const修饰成员函数:常量成员函数 这种成员函数不改变成员变量的值. 但被mutable 关键字修饰的成员变量,即使放在const成员函数里,它的值也可以被改变.

lambda显式声明返回值

10.21 编写一个lambda,捕获一个局部int变量,并递减变量值,直至它变为0.一旦变量变为0,再调用lambda应该不再递减变量.lambda应该返回一个bool值,指出捕获的变量是否为0. #include<iostream> #include<algorithm> using namespace std; int main() { int n=5; auto f=[n]() mutable ->bool {if(n>0) return --n;else re

php7函数,声明,返回值等新特性介绍

使用 ... 运算符定义变长参数函数 (PHP 5 >= 5.6.0, PHP 7) 现在可以不依赖 func_get_args(), 使用 ... 运算符 来实现 变长参数函数. function f($req, $opt = null, ...$params) { // $params 是一个包含了剩余参数的数组 printf('$req: %d; $opt: %d; number of params: %d'."\n", $req, $opt, count($params)

stdarg.h——用于函数接受可变参数

stdarg.h是C语言中C标准函数库的头文件,stdarg是由standard(标准) arguments(参数)简化而来,主要目的为让函数能够接收可变参数. 1.可变参数函数 声明可变参数函数 可变参数函数的参数数量是可变动的,它使用省略号来忽略之后的参数.例如printf函数一般.代表性的声明为: int check(int a, double b, ...); 可变参数函数最少要有一个命名的参数,所以 char *wrong(...); 在C中是不被允许的(在C++中,这样的声明是合理的

C#关键字扫盲——Tuple(元组类) 、ValueTuple(值元组)

原文:C#关键字扫盲--Tuple(元组类) .ValueTuple(值元组) 版权声明:本文为博主原创文章,随意转载. https://blog.csdn.net/Michel4Liu/article/details/79750877 Tuple.ValueTuple 当方法返回值大于一个时我们有时用out或结构体或类来处理,今天介绍一个简便的多返回值方式. ValueTuple 是 Tuple的扩展,本文只针对最新的ValueTuple 做讲解,Tuple有很多不便之处,总之过时的就让他过去