函数值和简单值


函数值和简单值

不分配绑定


我们再来看一下这个简单的函数:

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


优质内容筛选与推荐>>
1、html锚点及内联框架
2、C语言-指针
3、java web项目中 获取resource路径下的文件路径
4、html--字体大小
5、poj1753


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn