zoukankan      html  css  js  c++  java
  • 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 

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

  • 相关阅读:
    SQL 二进制和字符互转
    拒绝了对对象 'sp_OACreate' (数据库 'mssqlsystemresource',架构 'sys')的 EXECUTE 权限。
    SQL SERVER 正则替换
    SQL SERVER 算法执行效率
    webmin 安装
    MySQL5.6 PERFORMANCE_SCHEMA 说明
    flex 属性
    CSS 实现左侧固定,右侧自适应两栏布局的方法
    项目前端知识点
    为data中的某一个对象添加一个属性不起作用——this.$set的正确使用
  • 原文地址:https://www.cnblogs.com/FMax/p/1736085.html
Copyright © 2011-2022 走看看