施瓦茨變換

這可能是使用 Perl 的函數語言程式設計工具進行排序優化的最著名的例子,用於專案的排序順序取決於昂貴的功能。

# What you would usually do
@sorted = sort { slow($a) <=> slow($b) } @list;

# What you do to make it faster
@sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, slow($_) ] }
@list;

第一個例子的問題是比較器經常被呼叫並且一直使用慢速函式重新計算值。一個典型的例子是按檔案大小排序檔名:

use File::stat;
@sorted = sort { stat($a)->size <=> stat($b)->size } glob "*";

這樣可以工作,但最多隻會產生兩次系統呼叫的開銷,最壞的情況是它必須轉到磁碟,兩次,每次比較,並且該磁碟可能位於另一側的過載檔案伺服器中。行星。

進入 Randall Schwartz 的伎倆。

Schwartzian 變換基本上推動了 @list 的三個功能,從底部到頂部。第一個 map 將每個條目轉換為原始專案的雙元素列表,將慢函式的結果作為排序鍵,因此在結尾處我們為每個元素呼叫了 slow() 一次。然後,以下 sort 可以通過檢視列表來簡單地訪問排序鍵。由於我們不關心排序鍵但只需要排序順序的原始元素,最終的 map 會從 @sort 收到的已經排序的列表中丟棄兩個元素列表,並返回僅包含其第一個成員的列表。