F# 互動式程式設計
使用 F# 互動 (dotnet fsi),在主控台以互動方式執行 F# 程式碼,或執行 F# 指令碼。 換句話說,F# 互動會執行 F# 的 REPL (讀取、評估、列印迴圈)。
若要從主控台執行 F# 互動,請執行 dotnet fsi
。 將可以在任何 .NET SDK 中找到 dotnet fsi
。
注意
若要在 .NET Framework 執行階段下使用 F# 互動,您將需要安裝 Visual Studio Build Tools 或某個版本的 Visual Studio,並從開發人員命令提示字元叫用 FsiAnyCPU.exe
命令,或只要在 PATH
環境變數中將 FsiAnyCPU.exe
設定為可用,以代替 dotnet fsi
命令列。
支援定義版本 F# 互動執行階段的工具:
- 在 Visual Studio 中:在功能表列中,[工具] / [選項],然後 [F# 工具] / [F# 互動],並調整 [使用 .NET Core 指令碼]。
- 在 Visual Studio Code (ionide 延伸模組) 中:在命令選擇區中,[喜好設定: 開啟使用者設定],然後 [延伸模組] / [F#] / [FSharp: Fsi Sdk 檔案路徑]。
如需可用命令列選項的相關資訊,請參閱 F# 互動選項。
直接在 F# 互動中執行程式碼
由於 F# 互動是 REPL (讀取-評估-列印迴圈),因此您可以在其中以互動方式執行程式碼。 以下是從命令列執行 dotnet fsi
之後的互動式工作階段範例:
Microsoft (R) F# Interactive version 11.0.0.0 for F# 5.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
For help type #help;;
> let square x = x * x;;
val square : x:int -> int
> square 12;;
val it : int = 144
> printfn "Hello, FSI!"
- ;;
Hello, FSI!
val it : unit = ()
您會注意到兩個主要事項:
- 所有程式碼都必須以雙分號 (
;;
) 終止,才可進行評估 - 系統會評估程式碼,並將其儲存在
it
值中。 您可以以互動方式參考it
。
F# 互動也支援多行輸入。 您只需要以雙分號 (;;
) 來終止提交程序。 請考慮下列已貼入 F# 互動並由其評估的程式碼片段:
> let getOddSquares xs =
- xs
- |> List.filter (fun x -> x % 2 <> 0)
- |> List.map (fun x -> x * x)
-
- printfn "%A" (getOddSquares [1..10]);;
[1; 9; 25; 49; 81]
val getOddSquares : xs:int list -> int list
val it : unit = ()
>
程式碼的格式會保留,而且會有雙分號 (;;
) 終止輸入。 F# 互動會接著評估程式碼並列印結果!
F# 指令碼作業
在 F# 互動中以互動方式評估程式碼可謂絕佳的學習工具,但您很快就會發現,這無法像在一般編輯器中撰寫程式碼一樣有生產力。 若要支援一般程式碼編輯,您可以撰寫 F# 指令碼。
指令碼會使用副檔名 .fsx。 您只要執行 dotnet fsi,並指定 F# 原始程式碼的指令碼檔名,F# 互動就會即時讀取並執行程式碼,而不是先編譯原始程式碼,然後再執行已編譯的組件。 例如,請考量下列指令碼 Script.fsx
:
let getOddSquares xs =
xs
|> List.filter (fun x -> x % 2 <> 0)
|> List.map (fun x -> x * x)
printfn "%A" (getOddSquares [1..10])
在機器中建立此檔案後,您可以透過 dotnet fsi
來執行檔案,並在終端機視窗中直接查看輸出:
dotnet fsi Script.fsx
[1; 9; 25; 49; 81]
Visual Studio、Visual Studio Code 和 Visual Studio for Mac 為 F# 指令碼提供原生支援。
參考 F# 互動中的套件
注意
封裝管理系統是可延伸的,請參閱有關外掛程式與延伸模組機制 (英文) 的詳細資訊。
自語言的 5.0 版本以來,F# 互動就支援透過擴充性機制來參考封裝;它能以原生方式使用 #r "nuget:"
語法與選項版本來參考 NuGet 封裝:
#r "nuget: Newtonsoft.Json"
open Newtonsoft.Json
let data = {| Name = "Don Syme"; Occupation = "F# Creator" |}
JsonConvert.SerializeObject(data)
如果未指定版本,則會採用具最高可用性的非預覽版套件。 若要參考特定版本,請透過逗號來導入版本。 這項操作在參考預覽版套件時非常實用。 例如,請考慮這個使用預覽版 DiffSharp 的指令碼:
#r "nuget: DiffSharp-lite, 1.0.0-preview-328097867"
open DiffSharp
// A 1D tensor
let t1 = dsharp.tensor [ 0.0 .. 0.2 .. 1.0 ]
// A 2x2 tensor
let t2 = dsharp.tensor [ [ 0; 1 ]; [ 2; 2 ] ]
// Define a scalar-to-scalar function
let f (x: Tensor) = sin (sqrt x)
printfn $"{f (dsharp.tensor 1.2)}"
指定套件來源
您也可以使用 #i
命令來指定套件來源。 下列範例會指定遠端和本機來源:
#i "nuget: https://my-remote-package-source/index.json"
#i """nuget: C:\path\to\my\local\source"""
這會通知位於涵蓋範圍下的解析引擎,讓其也將新增至指令碼的遠端和/或本機來源納入考量。
您可以在指令碼中指定任何套件參考,而沒有數目上限。
注意
目前使用架構參考 (例如 Microsoft.NET.Sdk.Web
或 Microsoft.NET.Sdk.WindowsDesktop
) 的指令碼有一項限制。 無法使用 Saturn、Giraffe、WinForms 等套件。 此追蹤情況記錄在問題 #9417 中。
WinForms,在 F# 互動版本的 .NET Framework 中仍能運作。
除了 SDK 和/或您的工具隨附的延伸模組之外,若要載入其他延伸模組,請使用 --compilertool:<extensionsfolderpath>
旗標作為 F# 互動工作階段的引數 (或在您的工具設定中)。
使用 F# 互動來參考磁碟上的組件
或者,如果您的磁碟中有組件,且想在指令碼中參考該組件,您可以使用 #r
語法來指定組件。 請考慮將以下專案程式碼編譯為 MyAssembly.dll
:
// MyAssembly.fs
module MyAssembly
let myFunction x y = x + 2 * y
編譯之後,您可以在名為 Script.fsx
的檔案中參考組件,如下所示:
#r "path/to/MyAssembly.dll"
printfn $"{MyAssembly.myFunction 10 40}"
輸出如下所示:
dotnet fsi Script.fsx
90
您可以在指令碼中指定任何組件參考,而沒有數目上限。
載入其他指令碼
編寫指令碼時,針對不同工作使用不同指令碼通常會有所幫助。 有時候,您可能想在指令碼中重複使用另一個指令碼所用的程式碼。 您可以使用 #load
來直接載入並評估程式碼,而無須複製並將其內容貼到檔案中。
請考慮下列 Script1.fsx
:
let square x = x * x
以及取用的檔案 Script2.fsx
:
#load "Script1.fsx"
open Script1
printfn $"%d{square 12}"
您可以評估 Script2.fsx
,如下所示:
dotnet fsi Script2.fsx
144
您可以在指令碼中指定任何 #load
指示詞,而沒有數目上限。
注意
需要 open Script1
宣告。 這是因為 F# 指令碼中的建構會編譯成最上層模組,這是其所在的指令檔名稱。 如果指令檔有小寫名稱 (例如 script3.fsx
),則系統會將隱含的模組名稱自動改為大寫,而您則必須使用 open Script3
。 若要讓可載入的指令碼定義模組的特定命名空間建構,您可以包含模組宣告的命名空間,例如:
module MyScriptLibrary
在 F# 程式碼中使用 fsi
物件
F# 指令碼可存取自訂 fsi
物件,該物件代表 F# 互動工作階段。 其可讓您自訂輸出格式等項目。 這也是您可以存取命令列引數的方式。
下列範例示範如何取得和使用命令列引數:
let args = fsi.CommandLineArgs
for arg in args do
printfn $"{arg}"
進行評估時,其會列印所有引數。 第一個引數一律是評估的指令碼名稱:
dotnet fsi Script1.fsx hello world from fsi
Script1.fsx
hello
world
from
fsi
您也可以使用 System.Environment.GetCommandLineArgs()
來存取相同的引數。
F# 互動指示詞參考
先前看到的 #r
和 #load
指示詞僅適用於 F# 互動。 下列幾個指示詞僅適用於 F# 互動:
指示詞 | 描述 |
---|---|
#r "nuget:..." |
參考 NuGet 中的套件 |
#r "extname:..." |
參考來自 extname 延伸模組[^1] 的封裝 (例如 paket ) |
#r "assembly-name.dll" |
參考磁碟上的組件 |
#load "file-name.fsx" |
讀取原始程式檔、進行編譯,並加以執行。 |
#help |
顯示可用指示詞的詳細資訊。 |
#I |
指定加上引號的組件搜尋路徑。 |
#quit |
終止 F# Interactive 工作階段。 |
#time "on" 或 #time "off" |
#time 會自行切換是否顯示效能資訊。 當 F# 互動為 "on" 時,其會針對每個已解譯和執行的程式碼區段,測量即時、CPU 時間和記憶體回收資訊。 |
[^1]:深入了解 F# 互動延伸模組 (英文)。
當您在 F# Interactive 中指定檔案或路徑時,應該要有一個字串常值。 因此,檔案和路徑必須以引號括住,並遵循一般的逸出字元。 您可以使用 @
字元,讓 F# 互動將包含路徑的字串解譯為逐字字串。 這會導致 F# Interactive 會忽略所有逸出字元。
互動式和已編譯的前置處理器指示詞
當您編譯 F# 互動中的程式碼,無論是以互動方式執行或是執行指令碼,都會定義符號 INTERACTIVE。 當您在編譯器中編譯程式碼時,則會定義符號 COMPILED。 因此,如果已編譯模式和互動式模式中的程式碼必須不同,您可以使用條件式編譯的前置處理器指示詞,決定要使用哪一種模式。 例如:
#if INTERACTIVE
// Some code that executes only in FSI
// ...
#endif
在 Visual Studio 中使用 F# 互動
若要透過 Visual Studio 執行 F# Interactive,您可以按一下標示為 F# Interactive 的合適工具列按鈕,或使用按鍵 Ctrl+Alt+F。 如此會開啟互動式視窗,也就是執行 F# Interactive 工作階段的工具視窗。 您也可以選取要在互動式視窗中執行的部分程式碼,然後點擊按鍵組合 ALT+ENTER。 F# Interactive 會隨即在標示為 F# Interactive 的工具視窗中啟動。 當您使用這個按鍵組合時,請確定編輯器視窗具有焦點。
不論是使用主控台還是否 Visual Studio,命令提示字元都會出現,表示解譯器在等待您輸入。 您可以如同在程式碼檔案中一樣輸入程式碼。 若要編譯並執行程式碼,請輸入兩個分號 (;;) 以終止一或數行的輸入。
F# Interactive 會嘗試編譯程式碼,如果成功的話,它會執行程式碼,並列印它所編譯的類型與值的簽章。 如果發生錯誤,解譯器就會列印錯誤訊息。
在同一個工作階段中輸入的程式碼,可以存取先前輸入的所有建構,因此您可以建置程式。 若有需要,可利用 [工具] 視窗中的延伸緩衝區,視需要將程式碼複製到檔案。
在 Visual Studio 中執行 F# Interactive 時,會與專案分開執行,因此,舉例來說,除非您將函式的程式碼複製到 [互動] 視窗,否則無法使用在 F# Interactive 中專案內所定義的建構。
您可以調整設定來控制 F# 互動命令列引數 (選項)。 在 [工具] 功能表上,選取 [選項...],然後展開 [F# 工具]。 您只能變更 F# Interactive 選項和 [64 位元 F# Interactive] 這兩項設定,而且只有在 64 位元電腦上執行 F# Interactive 時才相關。 這項設定會判斷您要執行專用的 64 位元版 fsi.exe 或 fsianycpu.exe,其會使用機器結構來判斷要以 32 位元或 64 位元的處理序執行。
相關文章
標題 | 描述 |
---|---|
F# Interactive 選項 | 說明 F# 互動 (fsi.exe) 的命令列語法與選項。 |