如果你也會C#,那不妨了解下F#(1):F# 數據類型


本文鏈接:http://www.cnblogs.com/hjklin/p/fs-for-cs-dev-1.html

簡單介紹

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 SDKs\F#\4.0\Framework\v4.0\Fsi.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\n”;
string str = @"c:\filename";
let str = “abc\n”
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的類。

但是在F#中,只需在前后加上``即可將任意字符串指定為變量名:

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里嘗試輸入運算玩一玩,或許就可以發現區別了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM