PowerShellでfoldr(アール)

概要

foldlの時
http://d.hatena.ne.jp/kya-zinc/20091128
と同じように、
パイプから流れてきたオブジェクトをスクリプトブロックでたたみこむ。

実装

function Main
{
  1,2,3 | foldr {$_l + $_r * 100} 4
  1,2,3 | foldr_stack {$_l + $_r * 100} 4
  $null | foldr {$_l + $_r} 100
  $null | foldr_stack {$_l + $_r} 100
}

function foldr([ScriptBlock] $script, [Object] $last)
{
  $_r = $last
  $input_arr = @() + $input
  for($idx = $input_arr.Length - 1; $idx -ge 0; $idx--)
  {
    $_l = $input_arr[$idx]
    $_r = & $script
  }
  $_r
}

function foldr_stack([ScriptBlock] $script, [Object] $last)
{
  begin
  {
    $stack = New-Object System.Collections.Stack
  }
  
  process
  {
    $stack.push($_)
  }
  
  end
  {
    $_r = $last
    while($stack.Count -ne 0)
    {
      $_l = $stack.Pop()
      $_r = & $script
    }
    $_r
  }
}

. Main

実行結果

4030201
4030201
100
100

パイプ入力をすべて待ってから動作するので、
ストリーム処理っぽくない。
"@() + $input"の部分は列挙子(イテレータ?)を配列にするテクニック。
配列のインデックスを逆にたどる(foldr)のが気に入らなかったので
スタックでストリームを裏返してみた。(foldr_stack)
スタックのempty判定が見つからなかった…。