你是否正在寻找关于f#的内容?让我把最趣味的东西奉献给你:
这是系列文章的第二篇,读完本文后,您应当能够具备相当的阅读f#代码的能力。如果您没有看过第一篇,请看这里。
1.不可变性(Immutability)
您也许已经注意到,我一直使用值(value)来表示一个标识符(identifier),而不是变量(variable)。这是由于默认情况下,f#中的类型是不可变的(immutable),也就是说,一经创建即不可修改。看起来这是一个很大的限制,但是不可变性可以避免。另外,不可变的数据天然地具备线程安全的特性,这意味着您无需在处理并行情况时担心同步锁的发生。我将在系列的第三篇中介绍异步编程。
如果您确实需要修改数据,可使用f#的mutable关键字,它会创建一个变量(而不是值)。我们可以通过左箭头操作符(<-)来修改变量的值。
;;
> printfn x;;
x'
val it : unit = ()
> x ;;
val it : unit = ()
> printfn x;;
x'
val it : unit = ()
2. 引用值(Reference values,Microsoft.FSharp.Core.Ref<_>)
引用值是另一种表示可修改数据的方式。但它不是将变量存储在堆栈(stack),引用值其实是一个指向存储在堆(heap)上的变量的指针(pointer)。在f#中使用可修改的值时会有些限制(比如不可以在内部lambda表达式中使用)。而ref对象则可被安全地传递,因为它们是不可变的record值(只是它有一个可修改的字段)。
使用引用值时,用:=赋一个新值,使用!进行解引用。
;;
ref
> refCell := -1;;
val it : unit = ()
> !refCell;;
3. 模块(Modules)
在上篇文章中,我只是随意地声明了几个值和函数。您也许会问,要把它们放在哪里呢?,因为在C#中所有一切都要属于相应的类。尽管在f#中,我们仍然可以用熟悉的方式声明标准的.NET类,但它也有模块的概念,模块是值、函数和类型的集合(可以对比一下命名空间,后者只能包含类型)。
这也是我们能够访问List.map的原因。在f#库(FSharp.Core.dll)中,有一个名为List的模块,它包含了函数map。
在快速开发的过程中,如果不需要花费时间去设计严格的面向对象类型体系,就可以采用模块来封装代码,。要声明自己的模块,要使用module关键字。在下面的例子中,我们将为模块添加一个可修改的变量,该变量也是一个全局变量。
module ProgramSettings =
module MyProgram =
ProgramSettings.version
open ProgramSettings
debugMode := true
4. 元组(Tuples)
元组(tuple,发音为two-pull)表示值的有序集合,而这些值可看作一个整体。按传统的方式,如果您要传递一组相关的值,需要创建结构(struct)或类(class),或者还需要out参数。使用元组我们可以将相关的值组织起来,同时并不需要引入新的类型。
要定义一个元组,只要将一组值用逗号分隔,并用圆括号把它们括起来即可。
);;
>)=(x,x.ToString(),x*x);;
>getNumberInfo42;;
函数甚至可以接受元组为参数:
ownertitleurl;;
unit
>);;
>printBlogInfomyBlog;;
Chris
valit:unit=()
5. 函数柯里化(Function Currying)
f#提供的一个新奇的特性是可以只接受参数的一个子集,而接受部分参数的结果则是一个新的函数。这就是所谓的函数柯里化。比如,假设有一个函数接受3个整数,返回它们的和。我们可以只传入第一个参数,假设值为10,这样我们就可以说将原来的函数柯里化了,而它会返回一个新的函数——新函数接受两个整数,返回它们与10的和。
>letaddThreexyz=x+y+z;;
>xy;;
>addTwo;;
6. Union类型(Union Types,Discriminated Unions)
考虑下面的枚举值:
理论上,一个card实例只有一种可能的取值,但由于enum本质上只是整数,您不能确定它的值是否是有效的,在C#中,你可以这么写:
;
CardSuitinvalid2
另外,考虑下面的情形。如果您需要扩展一个enum:
enumTitle{Mr,Mrs}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shenmilingyu/article-1935-1.html
美国人那点手段不得人心
家里就0利息了
泻做尸叫兽