zoukankan      html  css  js  c++  java
  • F#(1)

    如果你也会C#,那不妨了解下F#(1):F# 数据类型

     

    简单介绍

    F#(与C#一样,念作“F Sharp”)是一种基于.Net框架的强类型、静态类型的函数式编程语言。
    可以说C#是一门包含函数式编程的面向对象编程语言,而F#是一门包含面向对象的函数式编程语言。
    可以查看官方文档了解更多信息。

    本系列文章假设你在了解C#的情况下,将F#与C#在异同点上进行说明,让读者能快速地对F#有个系统的了解。
    才疏学浅,错漏难免,如果您在阅读过程中有什么建议或意见,还请不吝指教。

    函数式编程这几年一起不温不火,但相信了解了F#之后,对C#也会有更深的认识,对学习其他函数式语言也会有很容易上手。

    Hello, World

    在使用F#时,可以像C#一样创建一个控制台项目进行测试。
    但因为F#支持以脚本形式运行,所以直接打开F# Interactive(以下简称fsi)进行交互是最方便的。

    在Visual Studio中可在“视图-其他窗口”中打开。以前没有csi的时候,一直拿fsi来测试C#代码,在VS2015中终于添加了csi。
    如果不想打开臃肿的VS,可在Microsoft SDK的安装位置找到fsi。以下是我安装的F# 4.0的fsi的位置:

    "C:Program Files (x86)Microsoft SDKsF#4.0Frameworkv4.0Fsi.exe"

    介绍任何语言的特有方式就是通过那几乎成为标准的“Hello, World”程序。
    F# 输出可使用 printf 函数,如下:

    printf "Hello, world!"

    当然,也可以像C#一样使用 .Net 的控制台输出函数:

    System.Console.Write("Hello World")

    当把以上代码敲进fsi里按回车后,会发现并没反应,是因为在fsi里提交代码必须以;;双分号结尾。
    请输入 printf "Hello, world!";; 和 System.Console.Write("Hello World");; 或者在换行后输入;;再次回车。
    如图:
    fsi

    F#基础类型

    下面,我们尝试把以下简单的C#代码转换成F#代码:

    int sum = 0; 
    for (int i = 0; i<=100; i++) 
    {     
        if (i%2 != 0)           
            sum += i; 
    } 
    Console.WriteLine("0到100中的奇数的和为{0}", sum);

    这段命令式代码只是简单地把0到100中的奇数相加,并把和输出。
    虽然在C#中也支持函数式,但在这里我们为了了解基本语法,使用简单语句来介绍。

    以下是F#版本的代码:

    let mutable sum = 0 
    for i = 0 to 100 do
        if i%2 <> 0 then sum <- sum + i 
    printfn "0到100中的奇数的和为%A" sum ;;

    以上代码在fsi里的运行结果为:

    0到100中的奇数的和为2500
    val mutable sum : int = 2500
    val it : unit = ()

    可以看出,F#中每行代码结尾的;是可选的。

    因为函数式编程语言的特点之一便是无副作用(No Side Effect)、不可变(Immutable),所以没有变量(Variable)的概念,只有值(Value)的概念。
    所以在上面的运行结果中,都是以val开头;而值it默认为最后一次运行结果,在此例中其类型为unit,相当于C#中的void,即无返回值。

    但是在很多场景下,Mutable(可变)可以带来很多便利,尤其是在像上面结合命令式编程的场景中。
    在上面的代码中,val mutable sum即为一个可变的值。

    基础类型

    下面将C#和F#的数据类型定义作对比:

    数据类型C#F#
    Int int i = 0; let i = 0 
    let i = 0l
    Uint uint i = 1U; let i = 1u 
    let i = 1ul
    Decimal decimal d = 1m; let d = 1m 
    let d = 1M
    Short short c = 2; let c = 2s
    Long long l = 5L; let l = 5L
    unsigned short ushort c = 6; let c = 6us
    unsigned long ulong d = 7UL; let d = 7UL
    byte byte by = 86; let by = 86y 
    let by = 0b00000101y 
    let by = ‘a’B
    unsigned byte sbyte sby = 86; let sby = 86uy 
    let sby = 0b00000101uy
    bool bool b = true; let b = true
    double double d = 0.2;
    double d = 0 .2d 
    double d = 2e-1 
    double d = 2 
    double d0 = 0
    let d = 0.2 
    let d = 2e-1 
    let d = 2. 
    let d0 = 0x0000000000000000LF
    float float f = 0.3;
    foat f = 0.3f;
    float f = 2;
    float f0 = 0.0f;
    let f = 0.3f 
    let f = 0.3F
    let f = 2.f 
    let f0 = 0x0000000000000000lf
    native int IntPtr n = new IntPtr(4); let n = 4n
    unsigned native int UIntPtr n = new UIntPtr(4); let n = 4un
    char char c = ‘c’; let c = ‘a’
    string string str = “abc ”;
    string str = @"c:filename";
    let str = “abc ” 
    let str = @"c:filename"
    big int BigInteger i = new BigInteger(9); let i = 9I

    F#的字面量详细介绍可查看MSDN文章

    十六进制、八进制和二进制

    我们知道,在C#中,可以用0x前缀定义十六进制数值。
    而F#中除了十六进制(0x,还可以直接定义八进制(0o)和二进制(0b的数值。

    let hex = 0xFABC
    let oct = 0o7771L
    let bin = 0b00101010y;;

    输出结果为:

    val hex : int = 64188
    val oct : int64 = 4089L
    val bin : sbyte = 42y

    浮点数

    需要注意的是,在F#里,doublefloat都代表双精度浮点数,单精度浮点数称为float32
    String还有一个字面量表示方法是三个双引号:

    let str = """<book title="Paradise Lost">
        <content />
    </book>"""

    在使用@为前缀(称为Verbatim String)时,字符串内的若出现双引号必须使用两个双引号转义,使用三个双引号的表示法避免了这个问题。
    这种表示法最常用在把XML文档编码到代码文件里。

    字节数组

    在类型对比表中,byte行可以看到有一个创建字节数组的语法:

    let asciiBytes = "abc"B  // val asciiBytes : byte [] = [|97uy; 98uy; 99uy|]

    其等价的C#代码是:

    byte[] asciiBytes = Encoding.ASCII.GetBytes("abc");

    当然,只支持ASCII编码。

    变量名

    F#的变量名命名规则与C#基本一致,但也可在变量名中包含单引号':

    let x = 10
    let x' = 11
    let Tom's = "2010"

    通过let关键字,将10绑定(赋值)到x,将11绑定到x'

    在C#中,若要将关键字或保留字作为变量名,则可以变量名前加@实现:
    例如使用代码

    class @class {}

    定义一个名为class的类。

    在前后加上``即可将任意字符串指定为变量名:

    let ``let`` = 4
    let ``I love F#`` = "This is an F# program."
    (*
        在fsi的输出结果为:
        val let : int = 4
        val ( I love F# ) : string = "This is an F# program."
    *)

    注意在F#中,单行注释和C#一样使用//,但多行注释使用(* *)

    F#的运算符与C#类似,部分区别将在下一篇介绍。感兴趣的可以在fsi里尝试输入运算玩一玩,或许就可以发现区别了。

  • 相关阅读:
    LeetCode 461. Hamming Distance
    LeetCode 442. Find All Duplicates in an Array
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode Find the Difference
    LeetCode 415. Add Strings
    LeetCode 445. Add Two Numbers II
    LeetCode 438. Find All Anagrams in a String
    LeetCode 463. Island Perimeter
    LeetCode 362. Design Hit Counter
    LeetCode 359. Logger Rate Limiter
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5763509.html
Copyright © 2011-2022 走看看