Image

像我這樣的菜鳥工程師,在 Coding 的時候時常會需要簡單試一些想法。像是「我這邊下了這串 Linq 出來的資料,到底是不是我想要的內容啊 = =?」

或是在進行開發任務時:「這個步驟能不能這樣做啊?先拆個簡單的 Method 試試看好了」之類的

以往遇到這種時候,我都會打開香香的 Linqpad 直接無情開寫,快速地作個小小的概念驗證。

畢竟 Linqpad 可以迅速地開始撰寫簡單的 C# 腳本,並且有良好的語法提示、Nuget 支援和方便的資料庫連線,省去我還要開一個 Console 專案自己弄這些東西,更可以存著之後備查,所以一直以來我都愛不釋手。

但在因緣際會下(其實就是閒逛論壇的時候),發現了微軟把拔出的 Polyglot Notebooks 這款 VSCode 擴充套件。當下驚為天人!Linqpad 在我心中的地位就這麼動搖了

Polyglot Notebooks 可以讓我們直接在 VSCode 上面撰寫簡單的 C#、F#、JavaScirpt 等腳本、迅速驗證想法。甚至可以對程式碼分段、加入 Markdown 文檔,讓我們能更有邏輯、有步驟地撰寫我們的腳本、處理我們的資料。

它的特色是這麼對我的胃口,看來我以後鐵定是會用到的。現在就來簡單記錄 Polyglot Notebooks 的使用方式吧!

安裝及建立檔案

首先我們需要先在 VSCode 找到「Polyglot Notebooks」這個擴充套件並安裝:

Image

安裝完畢之後,我們可以有兩種開啟方法:

  • 新增 ipynb 檔案再切換到 .NET Interactive 引擎
  • 使用 Polyglot Notebooks 的指令或快捷鍵,直接建立 dib 或 ipynb 檔案

補充:ipynb 檔案是用於撰寫 IPython Notebook 的檔案,也就是 Jupyter Notebook 在使用的檔案。而微軟把拔藉由 .NET Interactive 引擎讓 Jupyter Notebook 可以支援 C#, F#, SQL 等語言,讓 Notebook 可以支援多語言的撰寫,因此我們建立 ipynb 檔案也是可以撰寫 C# 的,感謝微軟把拔

由於我之前已經有在使用 Jupyter Notebook 撰寫 Python,因此這邊就以新增一個 ipynb 檔案進行示範:

Image

Image

建立了 ipynb 檔案之後,讓我們切換到 .NET Interactive 引擎

Image

現在我們已經可以看到讓我們 Coding 的儲存格了,這樣就完成準備工作啦!

補充:也可以使用 Ctrl+Shift+Alt+N 快捷鍵,或是 Ctrl+Shift+P 叫出 VSCode 的指令窗來下 Polyglot Notebook: Create new blank notebook 來直接建立檔案

這時候 VSCode 會詢問你要建立 .dib 或是 .ipynb,其中 .dib 進去就直接是 .NET Interactive 引擎,但目前還在實驗階段,並且 ipynb 還是以較常見的格式,因此我都還是選擇慣用的 .ipynb

開始撰寫腳本

首先當然要從 Hello world 開始啦,讓我們直接在儲存格裡面開寫:

Image

撰寫,然後按下全部執行或是左邊的單格執行

Image

切換腳本語言、加入更多儲存格

儲存格的右下角可以讓我們切換語言

Image

例如說我們可以來個 JavaScript:

Image

當然我們並不是只有這一個小小的儲存格能用(否則我前面就不敢說可以切步驟了嘛)

可以按下左上角的「+程式碼」來新增程式碼儲存格,或是把滑鼠移到儲存格最底部,會出現執行之後幫你往下新增一格的按鈕:

Image

現在我們可以同時放上兩個語言啦:

Image

我們也可以針對某一格來執行,或是用滑鼠選擇指定的儲存格,就可以選擇執行指定的儲存格以上或以下的部份,如果有修改某一格,然後要從修改的部分重跑一次的時候還挺方便的:

Image

此外還有複製貼上儲存格、合併儲存格等等操作,可以在上圖右邊紅框的「…」找到,這邊就不再贅述。

插入 Markdown 儲存格

眼尖的朋友應該發現了,上面新增儲存格的地方除了「+程式碼」以外,還有「+Markdown」的選項

畢竟 Polyglot Notebooks 這東西還是一本「筆記本」,只能貼 Code 不能寫筆記還算什麼筆記本呢,對吧?

因此我們可以在程式碼區塊之間適當地加入 Markdown 區塊,來提供需要的資訊,或是紀錄需要的筆記。讓我們撰寫的過程可以更有條理,之後回來閱讀也可以更快掌握內容。

除了在最底下新增儲存格的做法以外,我們也可以對指定的區塊上下來插入新儲存格:

Image

現在讓我們加入 Markdown 內容:

Image

執行之後就會變成文檔的一部分囉!

Image

如果 Markdown 有用到標題之類的,實測也可以進行摺疊:

Image

如此一來這份 Notebook 也可以當作一份文件來保存下去了,豈不美哉!

印出參數內容 & 簡單的 Linq 操作範例

現在來一點實境題:假設我現在想要試試看怎麼「取出列表裡面,依據特定欄位分組後,每一組的第一筆資料」

首先我們先做個測試用的 Class,並且捏一點測試用的假資料

接著直接呼叫參數來印出內容確認一下:

Image

現在我想要每一個 code 的第一筆,也就是 True 的那一筆。現在我覺得「也許 GroupBy 之後 Select 第一筆就搞定了吧?」

這時候我就可以在下面新增一個儲存格來做測試:

Image

搞定!現在我有信心使用這段 Code 了。還可以順便存成一個「分組取第一筆.ipynb」來讓以後的我可以抄,又是美好的一天。

安裝 Nuget 套件 & 簡單的呼叫 API 範例

2024.4.20 更新:後來時常連公司自家的 Nuget 抓內部套件,決定回來補一下指定 Nuget 的範例

平常開發的時候,我們還會運用各種套件來完成目標。

在 Polyglot Notebooks 裡可以使用 #r "nuget:{套件名稱}" 來安裝 Nuget 套件

此外,如果有需要指定 Nuget 套件來源,也可以使用 #i 來處理

#!c#
#i "nuget:https://api.nuget.org/v3/index.json"
#r "nuget:Newtonsoft.Json"
// 需要指定版本的話,可以在後面加上版本號。
// 例如:#r "nuget:Newtonsoft.Json, 12.0.3"

using Newtonsoft.Json;

var obj = new { Name = "James", Age = 30 };
var json = JsonConvert.SerializeObject(obj);
json // {"Name":"James","Age":30}

什麼是 Magic Commands

在前面安裝套件的時候,我們使用了 # 開頭的語法,這些語法被稱作「Magic Commands」

可以參考:Magic Commands 魔法命令 - dotnet/interactive

以下使用程式碼區塊(Cell)紀錄一些比較常用的 Magic Commands:

#!lsmagic
// 使用 #!lsmagic 來列出所有支援的 Magic Commands
// 或是參考 https://github.com/dotnet/interactive/blob/main/docs/magic-commands.md

#!csharp
// 使用 #!csharp 來指定語言為 C#
// 支援的語言有:#!csharp (#!c#, #!C#), #!fsharp (#!f#, #!F#)
// #!powershell (#!pwsh), #!javascript (#!js), #!html, #!markdown
#!time
// 使用 #!time 來計算 Cell 的執行時間

Console.WriteLine("Hello World!"); // Wall time: 32.5128ms
// 也能使用 #!mermaid 來讓 Mermaid.js 繪製流程圖

graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;

使用 #!set 來跨語言傳遞變數

2024.4.20 更新:用了一段時間之後,發現這東西的其中一個香點就在跨語言。趕緊回來補一下這段

當我們需要在兩個不同的程式語言之間傳遞變數,就可以使用 #!set

可參考:Variable sharing 變量共享

ps. #!share 誕生的比較早,但後來推出了更香的 #!set,所以這邊就只記 set 嚕 XD

#!c#

var fruitPrices = new Dictionary<string, int>
{
    {"apple", 10},
    {"banana", 20},
    {"cherry", 30}
};
// 同一個語言不需要特別傳遞也抓得到,所以這邊 Csharp 傳給 Csharp 不用做什麼處理
#!c#

var fruitPricesInCs = JsonConvert.SerializeObject(fruitPrices);
Console.WriteLine(fruitPricesInCs); 
// {"apple":10,"banana":20,"cherry":30}
// 現在讓我們到 JavaScript,這時候如果想從 Csharp 把變數拿過來,就需要用到 #!set
#!javascript
#!set --name fruitPricesInJs --value @csharp:fruitPrices

console.log(fruitPricesInJs); 
// {"apple":10,"banana":20,"cherry":30}

小結

這篇記錄了 Polyglot Notebooks 的基本用法,並且介紹了一些我覺得很香的地方:輕便快速的驗證風格、能像 Python 的 Jupyter NoteBook 逐步對資料進行處理,又有 C# 的 Linq 能用,用這東西寫個爬蟲之類的小腳本,邊跑隨改實在是舒適的體驗。

但同時因為這個工具還是 Preview 階段,被其他 IDE 養慣的我,已經習慣貼上語法之後讓 IDE 提示我 using 相關的命名空間進來了,因此像是 HttpClient 這種需要 using 的在這邊就很容易忘記,導致沒有跳自動完成提示的時候寫起來有點綁手綁腳(…說完感覺比較像是我的問題= = 我就菜)

總之身為一個當年用過 Jupyter Notebooks 的使用者,還是很看好這個工具後續的發展。輕便又能按步驟執行、又跨語言、又能插 Markdown 來做文檔,怎麼想都香!

太香了太香了,是不是該拿來刷題了啊?

2/28 補充,前面提到沒有自動完成提示的問題,在搭配 Github Copilot 之後,已經不是問題了!

例如說需要 using 的時候,Github Copilot 會幫忙補:

Image

安裝 Nuget 套件的時候,也會幫忙補上:

Image

甚至--

Image

原來 Polyglot Notebooks 搭配 Github Copilot 才是完全體啊!

果然還是該拿來刷…

參考資料