學習軌道
/
Lean
Lean
/
練習
/
平行字母頻率
平行字母頻率

平行字母頻率

中等

說明

使用平行運算計算多段文字中字母出現的頻率。

平行運算的重點,在於把那些也能循序完成的工作改成同時進行。 常見的例子就是計算字母出現的頻率。 請運用平行運算,計算由多段文字組成的陣列中,每個字母的總出現頻率。

非同步任務

任務是 Lean 中撰寫非同步程式碼的主要抽象機制。 它們很輕量,可以在另一個執行緒上平行執行,也可以在同一個執行緒上並行執行。

任務可以是純的,也可以是不純的。 純任務是用Task.spawn建立的,它接受一個純計算。 不純任務則是從IO計算建立的,例如使用IO.asTask,它會把IO α提升成IO monad 中的Task α。

在這個練習中,calculateFrequencies這個函式是 monadic 的,會回傳IO (Std.TreeMap Char Nat)。 因此可以透過IO.asTask使用不純任務,也能在回傳最終值之前建立純任務來進行中間計算。

避免資料競爭

身為函式語言,Lean 中大多數的值都是持久性的,也就是不可變的。 看似修改某個值的操作,實際上會產生一個帶有所要求變更的新值。 這表示記憶體通常可以在任務之間安全地共享,而不會產生資料競爭。

不過請注意,並非所有資料結構都同樣適合這種持久性的用法。 例如,更新Array中的單一元素通常需要複製整個陣列。 Std.HashSet和Std.HashMap也是如此。

為了讓這類資料結構更有效率,Lean 採用了參照計數。 只要某個值的參照是唯一的,就可以用破壞性的方式執行更新,避免不必要的複製。

其他資料結構,例如List、Std.TreeSet和Std.TreeMap,在設計上會在內部共享結構。 執行更新時,它們會重複使用沒有變動的節點,因此多個值可以共享這些節點的參照。 因此,修改結構中的某一部分通常不需要複製整個值。 這讓它們特別適合在任務之間共享。

測量執行速度

每個測試的執行時間都會用IO.monoNanosNow以奈秒為單位測量,並顯示在結果旁邊。 你可以試試不同的做法,看看它們對執行效能有什麼影響吧。

透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Lean Exercism

準備好開始 平行字母頻率 了嗎?

註冊 Exercism,透過 100 個練習 和真人引導來學習並精通 Lean,全部免費。

深入探索 平行字母頻率!

我們會探討並行與平行之間的差異,並看看 JavaScript、Go、Elixir 和 Rust 等語言採用的不同作法。