维基F#译文: 值与函数(中)

原文地址:http://en.wikibooks.org/wiki/F_Sharp_Programming

2. 声明函数

声明一个函数用的也是let,后面函数名和函数体,用空格间隔开来

let add x y = x + y
let z = add 5 10

定义一个叫add的函数,接受两个参数,然后返回相加的结果。这里z就等于15了。

那如果我这样调用呢?

let z = add 5 10.2

也许你会说z等于15.2吧,其实这里你会得到一个错误

error FS0001: This expression was expected to have type
    int
but here has type
    float

这是应该F#是一种强类型的语言,也就是说你5是一个整型,但是10.2却是浮点型。两个类型不一样,所以不能相加。如果你原来是写PHP的,或是其它弱类型的语言(相对强类型而言)。那你一定会觉得这个特性很烦。但是这也是有好处,比如说代码运行速度更快。

下面是一个稍微复杂的例子,注意最后一行的写法

let add x y = x + y
 
let sub x y = x - y
 
let printThreeNumbers num1 num2 num3 =
    printfn "num1: %i" num1
    printfn "num2: %i" num2
    printfn "num3: %i" num3
 
printThreeNumbers 5 (add 10 7) (sub 20 8)

最后一行在其它的语言里,也许是像下面这样写的,个人觉得F#的写法更省事,对于我这种懒人来说是福音。

printThreeNumbers( 5 , (add 10 7) , (sub 20 8) )

如果你像下面这样写的话,F#就会认为你传了7个参数给 printThreeNumbers 这个函数

printThreeNumbers 5 add 10 7 sub 20 8

2.1 函数返回值

不同于其它语言,在F#里你不用显示的调用return来返回值给调用者,简单的来说,函数里最后执行的语句所产生的值,就是这个函数的返回值。

let sign num =
    if num > 0 then "positive"
    elif num < 0 then "negative"
    else "zero"

上面所定义的函数sign,用来判断一个整数是正数还是负数,还是零。函数体内部没有显式的调用过return.但还是返回了值,也就是 positive negative zero这三个的其中一个,因为这个程序最后执行语句总是这三个分支中的其中一个。

那如果我返回不再类型的值呢,比如下面这样,最后返回的不是字符串zero而是整型0.

let sign num =
    if num > 0 then "positive"
    elif num < 0 then "negative"
    else 0

前面说了F#是强类型语言,和C#一样。所以这里会报错,因为你在同一个函数里,有可能返回两种不同数据类型的值。

最后要说的就是,如果一个函数没有返回值,那会怎么样,其实在F#中,如果一个函数没有返回值,它就会返回一种名为unit的类型的东西,其值为()。就是一对括号。那这个unit倒是什么,其实就相当于C语言中的void

let helloWorld = printfn "hello world"

比如上面这行代码,printfn的作用是向终端打印东西,在这里,printfn并没有返回值,所以helloWorld的值就是(),类型为unit

2.2 怎样读懂箭头类型提示符(Arrow Notation)

所有的函数和值在F#中都有数据类型,在函数式语言中,函数本身也可以作为值来传递。

let addAndMakeString x y = (x + y).ToString();;
val addAndMakeString : int -> int -> string

第一行你定义一个函数,然后输入;; 回车之后,F#就开始解释你这个函数了,他知道了你这个函数接受了两个参数,最后返回了一个值。于是就有了第二行的内容了。

按照箭头所指的方向,像流水一样,从左往右看。最右边的就是函数的返回值,剩下的就是函数所接受的参数。

所以在这里int -> int -> string 就表明这个函数的返回值是string,接受的参数有两个,从左向右,第一个参数是int型,第二个也是int型。再来看几个:

int -> string
float -> float -> float
int -> string -> float

第一行: 接受一个整型作为参数,返回字符串型。

第二行:接受一个浮点型作为第一个参数,再接受一个浮点型作为第二个参数,最后返回浮点型

第三行:接受一个整型作为第一个参数,再接受一个字符型作为第二个参数,最后返回浮点型

现在你也应该差不多理解这个东西了吧,你只要通过这个,不用看函数本身是怎么实现的,就能对这个函数明白个大概了。而F#又是怎么知道并且提示这个东西给你的呢,其实它是通过柯里化(Currying,这里取的是音译),或者叫部分求值来实现的,稍后会讲到这个。

原文地址:https://www.cnblogs.com/tuwenmin/p/2649503.html