函数值和简单值
不分配绑定
我们再来看一下这个简单的函数:
let add1 x = x + 1
"x"是什么意思呢?"x"意思是:
1:从输入值域中接收一些值
2:我们可以先用名字为“x”来表示值,以便之后引用它。
用名字表示值得过程称为"绑定(binding)",这个"x"是输入值的"确定值"。
如果我们以5为输入值计算这个函数,我们将会把原定义中看到的“x”替换为“5”,某种程度上这很像在文字上的查找替换。
let add1 x = x + 1 add1 5 // replace "x" with "5" // add1 5 = 5 + 1 = 6 // result is 6
明白这不是分配非常重要。"x“不是一个“插槽”或变量只是分配值给它,而且可以在以后分配另一个值给它。这只是名称“x”和值得一次性关联。这个值是已经定义的值,不能改变。而且,一旦确定,“x”也不能改变。一次关联一个值,总是关联一个值。
函数化思维中一个重要的观点:没有变量,只有值。
函数值
如果你思考得多一点,你会发现 名字为“add1”的本身,绑定给"输入值加一的函数"。函数本身是独立于它绑定到的名称的。
如果你输入"let add1 x=x+1",你是告诉F#编译器,当他看到add1的时候,就会用给输入加一的函数代替它。“add1”称为函数值。
为了了解函数是独立于它的名字,试一下:
let add1 x = x + 1 let plus1 = add1 add1 5 plus1 5
你可以看到”add1“和”plus1“引用(绑定)同样的函数。
你总是可以认出一个函数,因为他们有标准的签名”domain->range“。下边是一个函数值的泛型:
val functionName : domain -> range
简单值
想想一个没有输入总是返回整数5的操作
这是一个”常量“操作 。
在F#中怎么写呢?我们会告诉F#编译器,每次看到名字”c“,就会整数5替换它。
let c = 5
当它执行,返回:
val c : int = 5
这次没有箭头映射,只是一个整数。不一样的是打印实际值后有一个等号。F#编译器知道这个绑定总是返回一个值即5.
换句话说,我们定义了一个常量,在F#中是简单值。
你总是可以区分函数值和简单值,因为所有的简单值都有像这样的签名:
val aName: type = constant // Note that there is no arrow
简单值对比函数值
与C#不同,在F#中重要的是函数值和简单值是有一点不同的。他们都可以用名字来绑定(用let关键字)和传递。事实上,函数化编程的关键面之一是函数可以作为其他函数的输入值,我们很快就可以看到。
注意函数值和简单值微妙的不同。一个函数总是有一个域和一个范围,必须提供一个参数得到一个结果。一个简单值确定之后就不需要再计算。由于它们的不同,我们不得不这样去定义一个返回5的"常量函数"。
let c = fun()->5 // or let c() = 5
这些函数的签名是:
val c : unit -> int
而不是这样:
val c : int = 5
之后更多unit ,函数语法和匿名函数。
"值" 对比"对象"
在像F#这种函数式编程语言中,很多东西都叫做"值"。在像C#这样的面向对象语言中,很多东西都叫做"对象".那么他们之间有什么不同吗?
我们已经在前边知道,值只是域中的成员。整数域,字符串域,函数域,从整数到字符串的映射等等。原则上,值是不能改变的。而且值没有任何附加的行为。
对象,标准的定义是带有相关行为(方法)的数据结构的封装。总的来说,对象是有状态的(可以改变),所有改变内部的操作都必须由对象自己提供(用"."符号)。
在F#中,也有基元类型有类似对象的行为,例如,你可用"."出来获取字符串的长度。
"abc".Length
但是,总的来说,我们应该避免为标准值使用"对象",保留它是因为真实类的实例或者暴漏成员方法的其他值。
命名值
值和函数名的标准命名规则,基本上,任何字母字符串,包括下划线。有几个额外的:
你可以在名字用单引号,除了不能放在第一个位置,其他都可以。例如:
A‘b‘c begin‘ // valid names
最后的单引号通常是用来发出值的某种”变种”版本的标志:
let f = x let f‘ = derivative f let f‘‘ = derivative f‘
或者定义关键字的变形:
let if‘ b t f = if b then t else f
你可以在任何字符串使用双引号使它成为有效标识符。
``this is a name`` ``123`` //valid names
你可能想使用双引号标识符的时候
- 当你想使用一个与关键字相同的标识符时:
let ``begin`` = "begin"
- 当你想用自然语言描述业务规则,单元测试,BBD可执行规格风格时:
let ``is first time customer?`` = true let ``add gift to order`` = () if ``is first time customer?`` then ``add gift to order`` // Unit test let [<Test>] ``When input is 2 then expect square is 4``= // code here // BDD clause let [<Given>] ``I have (.*) N products in my cart`` (n:int) = // code here
不像C#,F#的函数和值得命名约定,首字母以小写开始而不是大写(骆驼命名而不是帕斯卡命名),除非专为暴露于其他.NET语言。可是类型和模块用首字母大写形式。
翻译有误,请指正,谢谢!
原文地址:http://fsharpforfunandprofit.com/posts/function-values-and-simple-values/
翻译目录传送门:http://www.cnblogs.com/JayWist/p/5837982.html
函数值和简单值