Emacsをお使いの皆さんは、if-let/when-letマクロをご存知でしょうか?
Rustには、以下のサンプルのようにパターンマッチを利用して便利に条件分岐できるif let構文があります。
if let Some(i) = letter {
println!("Matched {:?}!", i);
} else {
// Destructure failed. Change to the failure case.
println!("Didn't match a number. Let's go with a letter!");
}
Emacs Lispのif-let/when-letは、Rustのif letと同じものではありませんが、束縛される値がnilでないかどうかに応じて分岐する便利なマクロでした。
(if-let (c (get-letter-from-another-dimension))
(format "Matched %s" c)
"Not matched")
残念ながら、if-let/when-letは、Emacs 31.1(2024年12月現在の最新安定バージョンは29.4、もうすぐリリースされるのが30.1です)では廃止予定となり、if-let/when-letを使っているとコンパイル時に以下のような警告が表示されます。
Warning: ‘if-let’ is an obsolete macro (as of 31.1); use ‘if-let*’ instead.
if-let/when-letの代わりにif-let*/when-let*を使ってほしいとのことです。if-let*/when-let*では、以下のように1個以上の複数のバインディングを指定することができ、すべての値がnilでない場合にのみ真と判定されます。
(if-let* ((c1 (get-letter-from-another-dimension))
(c2 (get-letter-from-another-dimension)))
(format "Matched both %s and %s" c1 c2)
"At least one is not matched")
if-let/when-letを使っている既存のコードはすべて書き換えなければいけません。 以下の式をバッファ(ファイル)の先頭で評価すると、バッファ内のすべてのif-let/when-letがif-let*/when-let*に書き換えられます。 if-let/when-letを見つけたら修正PRを送りましょう。
(while (re-search-forward (rx symbol-start (or "when-let" "if-let") symbol-end) nil t)
(replace-match (concat (match-string 0) "*"))
(when (looking-at (rx (+ space)))
(goto-char (match-end 0)))
(insert-char ?\()
(forward-sexp)
(insert-char ?\)))