🌿
Lean 日報: [macro_inline] 属性で短絡評価にする
はじめに
この Lean 日報ではシリーズ記事として、Lean について新たに学んだことを書いていきます。定期更新ではありません。
短絡評価とは何か
「与えられた引数を全て評価するまでもなく値がわかるときには、残りの引数を評価しない」という評価戦略のことを 短絡評価 といいます。短絡評価が実装されている典型的な例は、論理演算子 &&
や ||
です。(それぞれ Lean で and と or の意味)他にも、デフォルト値を使って Option
に包まれた値をはがす関数 Option.getD
も Lean では短絡評価です。
「それって遅延評価じゃないの?」と思われたかもしれませんが、短絡評価は遅延評価より限定的です。無限リストを短絡評価を使って定義することはできませんが、遅延評価を使えば定義できます。
Lean は正格評価なので、引数を関数本体より先に評価します。つまり関数 f
に引数 a b c
を適用した値 f a b c
を評価する際には、a b c
の値をそれぞれ評価してから、それを f
に代入して評価しようとします。これは短絡評価と相性が悪いようですが、「評価前に関数をマクロ展開する」ことで短絡評価を実現しています。
短絡評価を実装する
著者は不勉強なもので、他のプログラミング言語で「短絡評価を実装する」ことがどの程度一般的なのか知らないのですが、Lean では特段の苦労なく実装することができます。それが標題の [macro_inline]
という属性です。この属性を関数に付与するだけで、その関数は「まるでマクロであるかのように」展開され、引数の評価が遅延されます。
/-- `Bool.and` を真似て自作した関数 -/
def Bool.myAnd : Bool → Bool → Bool
| true, true => true
| _, _ => false
-- 第二引数が評価されており、短絡評価になっていない
/--
info: hello
---
info: false
-/
#guard_msgs in
#eval Bool.myAnd false (dbg_trace "hello"; true)
-- `[macro_inline]` 属性を付与する
attribute [macro_inline] Bool.myAnd
-- 短絡評価になった!!
/-- info: false -/
#guard_msgs in
#eval Bool.myAnd false (dbg_trace "hello"; true)
より詳しくは Lean by Example の該当記事をご覧ください。
Discussion