Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

プログラミング全般 | 先行評価(eager evaluation)と遅延評価(lazy evaluation)

概要

先行評価(eager evaluation)と遅延評価(lazy evaluation)

詳細

先行評価(eager evaluation)と遅延評価(lazy evaluation)について

先行評価(eager evaluation)

即時にプログラムを評価する。
関数言語以外では標準的な手法。
関数言語以外でも大抵、遅延評価の仕組みが用意されている。

遅延評価(lazy evaluation)

実際に必要になってから評価する。
関数言語では標準的な手法。
分岐などがある際に、無駄な処理を実行させずに済むなどの利点がある。
詳細についてはサンプルコードをご覧ください。

また、遅延評価を行う場合は複数回呼び出される場合などに同じ処理を
二重実行してしまうケースがあるためメモ化など対策を立てる必要がある。

サンプルコード

先行評価はsome_long_conditionが実行されているが、
遅延評価は必要になってから実行するため、不要な処理を実行せずに済んでいる。

# encoding: utf-8

def some_long_condition(flg)
  puts "some long logic..."
  flg
end

# eager evaluation
def hoge(msg, heavy_condition)
  return if msg.empty?
  puts "#{msg}"
  heavy_condition ? "hello" : "world"
end

puts "eager valid msg some_long_condition(true)"
hoge "eager", some_long_condition(true)
puts "eager valid msg some_long_condition(false)"
hoge "eager", some_long_condition(false)
puts "eager invalid msg some_long_condition(true)"
hoge "", some_long_condition(true)
puts "eager invalid msg some_long_condition(false)"
hoge "", some_long_condition(false)

puts "------------------------------------"

# lazy evaluation
def hoge(msg, &heavy_condition)
  return if msg.empty?
  puts "#{msg}"
  heavy_condition.call ? "hello" : "world"
end

puts "lazy valid msg some_long_condition(true)"
hoge "lazy" do
  some_long_condition(true)
end
puts "lazy valid msg some_long_condition(false)"
hoge "lazy" do
  some_long_condition(false)
end
puts "lazy invalid msg some_long_condition(false)"
hoge "" do
  some_long_condition(true)
end
puts "lazy invalid msg some_long_condition(false)"
hoge "" do
  some_long_condition(false)
end

出力

eager valid msg some_long_condition(true)
some long logic...
eager
eager valid msg some_long_condition(false)
some long logic...
eager
eager invalid msg some_long_condition(true)
some long logic...
eager invalid msg some_long_condition(false)
some long logic...
------------------------------------
lazy valid msg some_long_condition(true)
lazy
some long logic...
lazy valid msg some_long_condition(false)
lazy
some long logic...
lazy invalid msg some_long_condition(false)
lazy invalid msg some_long_condition(false)