函数值和简单值

函数值和简单值

不分配绑定



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

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



函数值和简单值

时间: 2024-10-25 17:05:49

函数值和简单值的相关文章

简单值

在swift中使用 let 定义常量,使用 var 定义变量,常量在编译时可以不确定,但是你只能为他赋一次值,这就意味着你可以定义一个常量,然后在许多地方使用. 不论是常量还是变量,你赋值的类型必须和定义的类型相同.然而,你不用总是明确的指出(变量或者常量)是何种类型.当你定义一个变量或者常量是提供一个值让编译器判断它的类型. 如果初始值不能明确的指出何种类型(或者没有给出初始值),可以在变量后面加一个分号,后面跟上变量的类型 1 let implicitInteger=70; 2 let im

Swift -1- 简介&amp;简单值

1.简介: Swift是供iOS和OS X应?用编程的新编程语?言,基于C和Objective-C,却没有C的一些兼容约束.Swift采?用了安全的编程模式和添加现代的功能来使得编程更加简单.灵活和有趣.界面则基于?广受?人民群众爱戴的Cocoa和Cocoa Touch框架,展?示了软件开发的新?方向. 2.Swift入门 一个新语?言的学习应该从打印"Hello, world"开始.在Swift,就是一?行:println("Hello, world") 不同于C

Swift学习之简单值

常量关键字  let 变量关键字  var 数组和字典  ([]) \ () 格式字符串标记 在swift语法中使用let关键字声明常量,例如 let myConstant = 42 使用let声明的常量在编译时候不需要赋值,但是你必须在某个时候给它且只能赋值一次,意味着你可以声明一次,可以在许多地方使用多次. 使用var关键字声明变量,例如 var myVariable = 42 声明的let常量和var变量必须赋予相应的值,但是不需要每次都声明类型,因为编译器可以自动判断声明的变量类型. "

Swift中文教程(二)--简单值

原文:Swift中文教程(二)--简单值 Swift使用let关键字声明常量,var关键字声明变量.常量无需在编译时指定,但至少要被赋值一次.也就是说,赋值一次多次使用: 1 var myVariable = 42 2 myVariable = 50 3 let myConstant = 42 这里的常量赋值之后值不能更改,应该提高重用性. 一个常量或变量的值与类型必须是一致的.不过,你不需要指明它的类型,因为编译器会根据你所赋的值推断它的类型,在上面的例子中,编译器会判断到myVariable

Swift 001.简单值

使用`let`来声明常量,使用`var`来声明变量. 一个常量的值在编译时并不需要获取,但是你只能为它赋值一次. 也就是说你可以用常量来表示这样一个值:你只需要决定一次,但是需要使用很多次. var myVariable = 42 myVariable = 50 let myConstant = 42 常量或者变量的类型必须和你赋给它们的值一样. 然而,声明时类型是可选的,声明的同时赋值的话,编译器会自动推断类型. 在上面的例子中,编译器推断出`myVariable`是一个整数(integer)

Swift(一)简单值

按照国际惯例,学习一门新语言写的第一个程序都是在屏幕上输出一句 “Hello, world!” .在Swift里,一行代码就搞定了: 如果你以前写过C或者Objective-C的代码,这个语法你肯定看着很眼熟——在Swift里,这行代码就已经是一个完整的程序了.你不需要单独导入用于像输入/输出或者字符串处理功能的类库.写在全局范围内的代码就用来作为程序的入口点,所以不需要main函数.也不需要在每一行语句后面加上分号. 本系列教程通过完成一系列编程实例来提供给你足够的信息,让你能用Swift开始

Swift之旅(一)简单值

按照国际惯例,学习一门新语言写的第一个程序都是在屏幕上输出一句 "Hello, world!" .在Swift里,一行代码就搞定了: println("Hello, world!") 如果你以前写过C或者Objective-C的代码,这个语法你肯定看着很眼熟--在Swift里,这行代码就已经是一个完整的程序了.你不需要单独导入用于像输入/输出或者字符串处理功能的类库.写在全局范围内的代码就用来作为程序的入口点,所以不需要main函数.也不需要在每一行语句后面加上分号

Swift基础学习(四)简单值

使用 let 来声明常量,使用 var 来声明变量. 不用明确的声明类型,声明的同时赋值的话,编译器会自动推断类型.如果初始值没有提供足够的信息(或者没有初始值),那需要在变量名后面声明其类型,用冒号分割. var myVariable = 42 myVariable = 50 let myConstant = 42 let implicitInteger = 70 let implicitDouble = 70.0 let explicitDouble: Double = 70.0 // 明确

iOS开发-Runtime详解(简书)

简介 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的.比如: [receiver message]; // 底层运行时会被编译器转化为: objc_msgSend(receiver, selector) // 如果其还有参数比如: [receiver message:(id)arg...]; // 底层运行时会被编译器转化为: objc_msgSend(receiver, selector, arg1,