引数の評価についての認識間違い

前回(id:eji:20120619)の遅延ストリームを使った解答に若干修正を加えました。

stream.end <- function(msg) {
   msg == "eos"
}

stream.make <- function(head, tail) {
  function(msg) {
    if (msg == "eos") F
    else if (msg == "head") {
      head
    } else if (msg == "tail") {
      tail
    }
  }
}

stream.is_end <- function(s) {
  s("eos")
}

stream.head <- function(s) {
   s("head")
}

stream.tail <- function(s) {
   s("tail")
}

stream.take <- function(n, st) {
  if (n <= 0 || stream.is_end(st)) {
    stream.end
  } else {
    stream.make(
      stream.head(st),
      stream.take(n-1, stream.tail(st))
    )
  }
}

stream.take_while <- function(pred, st) {
  head <- stream.head(st)
  if (pred(head)) {
    stream.make(
      head,
      stream.take_while(pred, stream.tail(st))
    )
  } else {
    stream.end
  }
}
stream.fold <- function(fn, init, st) {
  if (stream.is_end(st)) init
  else {
    stream.fold(
      fn,
      fn(init, stream.head(st)),
      stream.tail(st)
    )
  }
}

stream.sum <- function(stream) {
  stream.fold(
    function(a, b) { a + b },
    0,
    stream
  )
}

stream.filter <- function(pred, st) {
  head <- stream.head(st)
  tail <- stream.tail(st)

  if (stream.is_end(st)) st
  else if (pred(head)) {
    stream.make(
      head,
      stream.filter(pred, tail)
    )
  } else {
    stream.filter(pred, tail)
  }
}

stream.fib <- (function() {
  fibgen <- function(a, b) {
    stream.make(
      a,
      fibgen(b, a+b)
    )
  }
  fibgen(1, 2)
})()

even <- function(n) {
  (n %% 2) == 0
}

answer <- stream.sum(
  stream.take_while(
    function(n) { n < 4000000 },
    stream.filter(even, stream.fib)
  )
)

cat("answer:", answer, "\n")

遅延評価のためにクロージャで包んでいたストリームの残りを、クロージャで包まないようにしました。Rでは渡された実引数が必要になった時に初めて評価されるため、わざわざクロージャで包んで評価を遅らせる必要がないようです。

例えば、Schemeのような正格評価の言語の場合、以下のようなコードでは第2引数に渡された値は(順番はどうあれ)評価されてしまいます。

; scheme
> (define (func a b)  a)
func
> (func 3 (display "hoge\n"))
hoge
3
>

しかし、Rの場合は引数の値が全く利用されなければ評価されません。

# R
> func <- function(a, b) a
> func(3, cat("hoge\n"))
3
>

RはHaskellと同じように非正格評価の言語なのかな...?