• F#小记——2. 基本数据类型


    F#基本数据类型:

    数字:

    C#一样,F#的数字类型和.net中的类型是一一对应的,只不过为了方便使用,又对其定义了一套别名而已,可以通过后缀区分其数据类型。

    类型

    后缀

    .NET 类型

    byte

    uy

    System.Byte

    sbyte

    y

    System.SByte

    int16

    s

    System.Int16

    uint16

    us

    System.UInt16

    int,int32

    System.Int32

    uint, uint32

    u

    System.UInt32

    int64

    L

    System.Int64

    uint64

    UL

    System.UInt64

    float

    System.Double

    float32

    f

    System.Float

    decimal

    M

    System.Decimal

    另外,也可以通过前缀0x0o0b来标识十六进制、八进制和二进制数据。

    > let hex = 0xFCAF;;

    val hex : int = 64687

    > let oct = 0o7771L;;

    val oct : int64 = 4089L

    > let bin = 0b00101010y;;

    val bin : sbyte = 42y

    > (hex, oct, bin);;

    val it : int * int64 * sbyte = (64687, 4089, 42)

    运算:

    数学运算是函数式编程的强项,F#提供了非常丰富的运算符

    • 基本运算:     +-*/%**
    • 位运算:         &&&|||^^^<<<>>>
    • 布尔运算:     &&||not
    • 比较:              <<=>>==<>compare
    • 数学函数:     abs ceil exp floor sign log log10 cos sin tan pown

    字符和字符串:

    F#中的字符和字符串和C#类似,就不多做介绍了。

    Unit

    Unit类型主要用于函数的返回值,用来表示函数不需要返回任何数据,类似于C#中的voidUnit类型可以用()来表示:

    > let x = ();;

    val x : unit

     

    > ();;

    val it : unit = ()

    如同C语言里不使用返回值不是void类型的函数的返回值会得到一条pclint告警一样,使用了返回值不是unit的函数也会得到一条告警:

    > let square x = x * x;;

    val square : int -> int

     

    > square 4;;

    val it : int = 16

    Warning 1   This expression should have type 'unit', but has type 'int'. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name.

    为了消除这个告警,我们可以使用系统内置的ignore函数。ignore函数返回一个unit类型,其功能如下:

    let ignore x = ()

    因此使用了ignore函数后,就改变了返回值为unit,自然就消除了这个告警。

    > ignore (square 4);;

    val it : unit = ()

    但是,这样写不是很优雅,我们常常通过管道符函数‘|>’来写成如下形式

    > square 4 |> ignore;;

    这种方式让我想起来了在unixshell重定向时常用的“… > null 0”结构。

    Tuples

    Tuples两个或多个值的集合,基本形式如下:

    > let dinner = ("green eggs", "ham");;

    val dinner : string * string = ("green eggs", "ham")

     

    > let zeros = (0, 0L, 0I, 0.0);;

    val zeros : int * int64 * bigint * float = (0, 0L, 0I, 0.0)

    其中,小括号是可选的,如下形式也合法,但不推荐。

    > let dinner = "green eggs", "ham";;

    获取Tuples中的元素值通常有如下两种方式:

    1.       通过系统内置的fstsnd函数

    > let a = fst (1, 2);;

    val a : int = 1

     

    > let b = snd (1, 2);;

    val b : int = 2

    2.       通过let绑定

    > let (a, b) = (1, 2);;

    val b : int = 2

    val a : int = 1

    可能有细心的朋友已经注意到了,系统只提供fstsnd函数,如果要对Tuples的第三个或以上元素该如何做呢?当然还是可以通过这两种方法啦:

    1.       自定义third函数,然后通过函数获取

    > let third (a, b, c) = c;; //由于这里不关心前两个元素,这个函数也可以写成let third (_, _, c) = c;;

    val third : 'a * 'b * 'c -> 'c

     

    > third (1, 2, 3);;

    val it : int = 3

    2.       通过let绑定的方式

    > let (_, _, c) = (1, 2, 3);;

    val c : int = 3

    这两种方式都是异曲同工的,我个人更喜欢let绑定的方式,用起来更加简洁优雅。

    Lists

    ListsF#中内置的链表,基本形式如下:

    > [];; //empty list

    val it : 'a list = []

    > [1; 2; 3];;

    val it : int list = [1; 2; 3]

    注意:List中元素是通过 ‘;’ 来分隔的,不要像C#那样用 ‘,’ 来分隔,一旦用了 ‘,’ ,得到的将是一个包含一个Tuples元素的List

    > [1, 2, 3];;

    val it : (int * int * int) list = [(1, 2, 3)]

    另外,我们也可以通过推导的方式,写出步长和范围,让系统自动推导List中的其它元素。

    > [1 .. 10];;

    val it : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

    > [1 .. 10 .. 50];;

    val it : int list = [1; 11; 21; 31; 41]

    :: 来连接List的头和尾

    一个List有一个“头”(第一个元素)和一个“尾”(剩下的元素)。头是一个元素,而尾则是一个列表。例如,对于[1; 2; 3]来说,表头是整数1,而表尾是list[2; 3]

    F#中,可以通过::运算符来连接头和尾,下面几种的列表写法是完全等价的:

    [1; 2; 3]

    1 :: [2; 3]

    1 :: 2 :: [3]

    1 :: 2 :: 3 :: []

    这个运算符主要用于模式匹配,在讲模式匹配的时候再介绍其用途。

    @ 来连接两个List

    类似于字符串可以用 + 运算符来连接一样,系统也内置了一个 @ 运算符来连接两个List,生成一个新的List

    > // Using the append operator

    let odds = [1; 3; 5; 7; 9]

    let evens = [2; 4; 6; 8; 10]

    val odds : int list = [1; 3; 5; 7; 9]

    val evens : int list = [2; 4; 6; 8; 10]

     

    > odds @ evens;;

    val it : int list = [1; 3; 5; 7; 9; 2; 4; 6; 8; 10]

     

    yield来返回一个List

    当函数返回值是一个List的时候,用上面的几种方式来构造List往往不是很方便,特别是在不确定元素个数的时候。因此,F#提供了一个关键字yield来方便我们构造List的返回值。

    > // Simple list comprehensions

    let numbersNear x =

        [

            yield x - 1

            yield x

            yield x + 1

        ];;

    val numbersNear : int -> int list

     

    > numbersNear 3;;

    val it : int list = [2; 3; 4]

    使用方式基本上和C#中的yield差不多,简单而方便。

    Option

    C#中,当无法获取到预期对象的时候,我们往往用null来标示这个值为空。这样导致我们再使用它的时候往往需要判断对象是否为null,多加判断会导致代码可读性差,漏加判断常常导致程序的一些bugC/C++会导致更严重的数据访问异常)。

    F#中,通过引进option类型来解决这一问题:option类型的数据的值有两种类型——Some('a) None,通过它们可以区分数据是否为空数据。

    > // Using option to return a value (or not)

    open System

    let isInteger str =

        let successful, result = Int32.TryParse(str)

        if successful then Some(result)

    else None;;

    val isInteger : string -> int option

     

    > isInteger "This is not an int";;

    val it : int option = None

     

    > isInteger "400";;

    val it : int option = Some 400

    要获取option中的元素值,可以通过Option.get函数来实现,当值为None的时候,Option.get会抛异常。如果要避免这个异常,可以通过Option.isSomeOption.isNone先判断一下。通过模式匹配可以更好的实现这一功能。

    let printNumber str =

        match (isInteger str) with

        | Some(num) -> printfn "Number: %d" num

    | None       -> printfn "Invalid Number"

    实际上,option也无法避免空值的判断,但是F#通过option明确指出了哪些需要判断,哪些不需要判断,这样对我们的代码无疑是非常有帮助的。

    其它数据类型:

    除了上述这几种基本类型以外,还有几种类型:Recordstructclass,Discriminated Unions等,这些的使用方法相对复杂点,在后续讲述函数式编程的时候再详细讲。

     

  • 相关阅读:
    博客园美化-打赏代码
    苹果appID的获取方法
    简体、繁体相互转换
    iOS Socket编程(一)基本概念
    无线通信
    http与https通信
    iOS开发网络篇—发送GET和POST请求(使用NSURLSession)
    iOS开发网络篇—GET请求和POST请求的说明与比较
    iOS开发网络篇—HTTP协议
    Verify the Developer App certificate for your account is trusted on your device.
  • 原文地址:https://www.cnblogs.com/TianFang/p/1774013.html
Copyright © 2020-2023  润新知