F#学习笔记方法

在上篇笔记里介绍完了F#里的基本类型,现在该介绍如果定义方法了。在F#里,定义一个方法跟定义一个基本类型的数据一样,语法是:

let squart x = x * x;;

square是函数名,第一个x是参数,等号后面的部分就是函数的主体部分了。在F#中,函数是没有return关键字的,方法总是返回函数体内的最后一行代码的结果作为方法的结果。在上面的例子中x * x就是这个方法的返回结果。

执行let squart x = x * x;;将得到:

val squart : int –> int

这个可以读作:方法squart获取一个int参数并且返回一个int类型的结果。

而下面这个方法:

let add x y = x + y;;

的执行结果是:

val add : int -> int –> int

这个的读法稍微复杂些:方法add获取一个int参数并且返回一个获取一个int参数并返回一个int结果的方法。呵呵,读起来有点绕口。

在定义方法的时候,很多情况下,我们可以忽略指定参数的类型,F#的编译器会根据代码的上下文推断出参数的类型,以及方法的返回类型。在上面的add方法的例子里,由于没有其他的代码,F#的编译器把参数的类型默认为int类型,如果现在执行:

add 1.0 2.0;;

将得到下面的错误:

  add 1.0 2.0;;
  ----^^^

stdin(7,5): error FS0001: This expression was expected to have type
    int   
but here has type
    float

但是如果是这样:

let add x y = x + y

let sum = add 1.0 2.0

就可以得到正确结果:

val add : float -> float -> float
val sum : float = 3.0

这个时候,方法的参数类型就变成了float类型。或者,我们可以在方法的定义中明确的指出参数的数据类型:

let add (x : float) y = x + y;;

val add : float -> float –> float

由于'+'运算的2个参数的类型是一致的,所以我们只需要指定其中1个参数的类型。

那这样可不可以呢:

let add x y = x + y

let sum = add 1 2

let sum = add 1.0 2.0;;

答案是悲剧的:

  let sum = add 1.0 2.0;;
  --------------^^^

stdin(20,15): error FS0001: This expression was expected to have type
    int   
but here has type
    float  

第二个调用会报异常。原因是第一个调用决定了方法参数的类型。

 

泛型方法

观察下面方法:

let op x = x;;

得到:

val op : 'a –> 'a

上面的这个方法也等效于:

let op (x : ‘a) = x;; //这个就是明确的指出这个方法是个泛型方法

'a在这里就表示了一个泛型参数。这是由于在这个方法中,任意类型的参数都可以使方法成立。那在之前的add方法的例子里有没有可能也定义成一个泛型方法呢?没有。这是由于在支持'+’运算的类型中,无论是int还是float或者其他的,它们没有一个共同的基类或者接口是支持'+’运算的,类型object肯定是不支持的,也就是说没办法提供一个约束来限定参数的类型范围,所以,编译器没办法根据let sum = add 1 2 & let sum = add 1.0 2.0推断出一个泛型方法同时可以支持int和float类型。还是C#的自动类型转换好啊,呵呵。

 

作用域

每一个被定义的数据都有它的作用域,在F#里,需要记住的是,每个值在使用前,它应该是被定义过的,也就是说定义的代码必须出现在使用它的代码之前。默认情况下,数据总是被定义在module里的,所以,在被定义之后,去其他地方可被任意使用。我将用几个例子来描述下F#里的作用域,例子总是最好的文档,对吧?:)

let moduleValue = 10

let f x = x + moduleValue;; // after declared, you can use it.

但是:

let f x =

    let functionValue = 10

    x + functionValue

functionValue;; // this is a wrong example

stdin(34,1): error FS0039: The value or constructor 'functionValue' is not defined

接下来,再看个复杂点的例子:

let GigaBytes x =

    let x = x / 1024I // 第二个x是方法参数的x,而第一个x则是方法内定义的x

    let x = x / 1024I // 第二个x是上一行定义的x,而非参数x,而第一个x则将覆盖掉上一行定义的x。这里let x = x / 1024I,并不是将原本的x的值修改为 x / 1024I,而是重新定义了一个值。

    let x = x / 1024I

    x;;

let x = GigaBytes (1I <<< 31);;

val it : System.Numerics.BigInteger = 2 {IsEven = true;
                                         IsOne = false;
                                         IsPowerOfTwo = true;
                                         IsZero = false;
                                         Sign = 1;}

结果是2。呵呵。

IF .. THEN .. ELSE ..

你可以在方法内部使用条件控制语句:if .. then .. [else ..]。

let f x =

    if x % 2 = 0 then

        printfn “it’s Even”

    else

        printfn “it is not”;;

或者

let f x =

    let result =

        if x % 2 = 0 then true

        else false

    result;;

嵌套

let f x =

    let result =

        if x % 2 = 0 then

            1

        else

            if x % 3 = 0 then

                2

            else

                3

    result;;

也可以简写成

let f x =

    let result =

        if x % 2 then 1

        elif x % 3 then 2

        elif x % 5 then 3

        else 4;;

如果存在else的情况下,if .. then 以及 else 返回的数据类型必须一致。

> let f x =
    if x % 2 then
        1
    else
        false;;

          false;;
  --------^^^^^

stdin(124,9): error FS0001: This expression was expected to have type
    int   
but here has type
    bool 

好了,目前为止,怎么写一个方法应该没什么问题了。

原文地址:https://www.cnblogs.com/FMax/p/1736085.html