zoukankan      html  css  js  c++  java
  • F# 语法概览

    F#和C#的语法差别

    语法上,F#和C#有两个主要差别:

    • 用缩进而非花括号分隔代码块
    • 用空白而非逗号分隔参数

    F#常见语法元素

    以下是F#代码中常见的语法元素

    注释

    // 这是单行注释
    (* 这是多行注释
    第二行
    最后一行 *)

    let 绑定

    let myInt = 5
    let myFloat = 3.14
    let myString = "hello"

    上面的语句没有显式指定 myInt, myFloat, myString 的类型,类型由编译器推断。

    列表

    let twoToFive = [2;3;4;5]        // 方括号表示列表,元素用分号分隔
    let oneToFive = 1 :: twoToFive   // 符号 :: 将值添加到列表头部,得到新列表,结果为 [1;2;3;4;5]
    let zeroToFive = [0;1] @ twoToFive   // 符号 @ 连接两个列表,得到新列表,结果为 [0;1;2;3;4;5]

    务必注意,列表元素使用分号分隔,而非逗号分隔。

    函数

    命名函数用 let 关键字定义,匿名函数用 fun 关键字定义。

    let square x = x * x          // 使用 let 定义命名函数,函数形参不用小括号围住
    square 3                      // 运行函数,实参也没有小括号
    
    let add x y = x + y           // 不可使用 (x,y)
    add 2 3                       // 运行函数
    
    // 多行函数,用缩进,不用分号
    let evens list =
       let isEven x = x%2 = 0     // 内部函数
       List.filter isEven list    // List.filter 是库函数
    
    evens oneToFive               // 运行函数
    
    // 用小括号指明优先级
    let sumOfSquaresTo100 =
       List.sum (List.map square [1..100]) // 如果没有小括号,那么 List.map 会是 List.sum 的参数
    
    // 管道 |>,将操作的输出传给下一个操作
    let sumOfSquaresTo100piped =
       [1..100] |> List.map square |> List.sum
    
    // 用 fun 关键字定义拉姆达(匿名函数)
    let sumOfSquaresTo100withFun =
       [1..100] |> List.map (fun x->x*x) |> List.sum

    模式匹配

    match..with 用于模式匹配

    // 类似于 switch/case
    let
    simplePatternMatch = let x = "a" match x with | "a" -> printfn "x is a" | "b" -> printfn "x is b" | _ -> printfn "x is something else" // 下划线匹配任意值 // Some(..) 和 None 有点像可空类型(Nullable) let validValue = Some(99) let invalidValue = None // match..with 匹配 "Some" 和 "None",同时从 Some 中取出值 let optionPatternMatch input = match input with | Some i -> printfn "input is an int=%d" i | None -> printfn "input is missing" optionPatternMatch validValue optionPatternMatch invalidValue

    复杂类型

    复杂类型是指元组,记录和联合

    // 元组,包含有序但未命名的值,值之间用逗号分隔
    let twoTuple = 1,2           // 二元组
    let threeTuple = "a",2,true  // 三元组
    
    // 记录,包含命名的字段,字段之间用分号分隔
    type Person = {First:string; Last:string}
    let person1 = {First="john"; Last="Doe"}
    
    // 联合,包含选项,选项之间用竖线分隔
    type Temp = 
        | DegreesC of float
        | DegreesF of float
    let temp = DegreesF 98.6
    
    // 类型可以递归的组合,例如,下面的 Employee 联合包含 Employee 类型的列表
    type Employee = 
      | Worker of Person
      | Manager of Employee list
    let jdoe = {First="John";Last="Doe"}
    let worker = Worker jdoe

    格式化输出

     printf 和 printfn 向控制台输出,类似于 C# Console 类的 Write 和 WriteLine 方法。sprintf 输出到字符串,类似于 String 类的 Format 方法。

    printfn "Printing an int %i, a float %f, a bool %b" 1 2.0 true
    printfn "A string %s, and something generic %A" "hello" [1;2;3;4]
    
    // 复杂类型具有内置的美观输出格式
    printfn "twoTuple=%A,
    Person=%A,
    Temp=%A,
    Employee=%A" twoTuple person1 temp worker
    
    let str1 = sprintf "Printing an int %i, a float %f, a bool %b" 1 2.0 true
    let str2 = sprintf "A string %s, and something generic %A" "hello" [1;2;3;4]

    比较F#和C#:计算平方和

    C#版,不使用 linq

    public static class SumOfSquaresHelper
    {
       public static int Square(int i)
       {
          return i * i;
       }
    
       public static int SumOfSquares(int n)
       {
          int sum = 0;
          for (int i = 1; i <= n; i++)
          {
             sum += Square(i);
          }
          return sum;
       }
    }

    F#版

    let square x = x * x
    let sumOfSquares n = 
       [1..n]               // 创建 1 到 n 的列表
       |> List.map square   // 对每个元素求平方,得到新列表
       |> List.sum          // 将平方列表求和

    F# 语法噪音小,没有花括号,分号,并且在这里不需要显式指定类型。

    C#版,使用 linq

    public static class FunctionalSumOfSquaresHelper
    {
       public static int SumOfSquares(int n)
       {
          return Enumerable.Range(1, n)
             .Select(i => i * i)
             .Sum();
       }
    }

    使用 linq 改写的 C# 代码简洁很多,但不能消除语法噪音,参数和返回值的类型也是必须的,仍然不如 F# 版简洁。

    例子:快速排序算法

    快速排序算法的步骤是:

    1. 从列表中取出一个数作为基准
    2. 将小于基准的数放在左边,不小于基准的数放在右边
    3. 对基准两边的部分进行快速排序

    下面是 F# 实现快速排序的例子

    let rec quicksort list =
       match list with
       | [] -> []
       | firstElem::otherElements ->  
    // 小于第一个元素的元素
    let smallerElements = otherElements |> List.filter (fun e -> e < firstElem) |> quicksort

    // 不小于第一个元素的元素 let largerElements = otherElements |> List.filter (fun e -> e >= firstElem) |> quicksort

    // 连接成新列表
    List.concat [smallerElements; [firstElem]; largerElements]
    printfn "%A" (quicksort [1;5;23;18;9;1;3])

    如果应用库函数和一些技巧,代码可压缩成:

    let rec quicksort = function
       | [] -> []                         
       | first::rest -> 
            let smaller,larger = List.partition ((>=) first) rest 
            List.concat [quicksort smaller; [first]; quicksort2 larger]

    参考网站:http://fsharpforfunandprofit.com/

  • 相关阅读:
    C语言程序设计100例之(12):Eratosthenes筛法求质数
    C语言程序设计100例之(11):求质数
    C语言程序设计100例之(10):最大公约数
    C语言程序设计100例之(9):生理周期
    C语言程序设计100例之(8):尼科彻斯定理
    C语言程序设计100例之(7):级数求和
    C/C++ 内部连接与外部连接
    C/C++ 内存管理问题
    C/C++浮点数的比较
    C/C++规范
  • 原文地址:https://www.cnblogs.com/dongbeifeng/p/fsharp-syntax-overview.html
Copyright © 2011-2022 走看看