ごとけんです

分岐のことを考えていて思い出したのですが、非一様に作用する 
Array#filter を使いたいときが結構あるような気がします。そこ
で非一様な Array#mold というのを書いてみました。

mold {|b0, ..., bn| ... }
mold(i1, ..., in) { |b1, ..., bn| ... }

  配列を返すブロックを指定します。引数を指定しない場合、ブロッ
  ク変数を self の各要素に代入してブロックを実行します。引数を
  した場合、引数を添字とする self の要素をブロック変数に代入し
  てブロックを実行し、引数で指定した位置の要素を置換した配列を
  返します。引数の数やブロックを評価した値の要素数に矛盾がある
  と例外を起こします。

class Array
  def mold(*ind, &blk)
    if ind.empty?
      unless (a = self.size) == (b = blk.arity)
	raise ArgumentError.new("no match arg# (`#{b}' for #{a})") 
      end
      yield(*self)
    elsif (a = ind.size) != (b = blk.arity)
      raise ArgumentError.new("no match arg# ((#{a}) vs |#{b}|)") 
    else
      diff = yield(*self.indices(*ind))
      if a != (b = diff.size)
	raise ArgumentError.new("block size != arg# (`#{b}' for #{a})") 
      end
      res = self.dup
      ind.each_with_index{|i,j| res[i] = diff[j]}
      res
    end
  end
end

$_ = "foo 12 3.4 56"
name, x, y, rot = split.
  mold(1,2,3){|a,b,c| [a.to_i, b.to_f, format("%04d", c.to_i)]}

-- gotoken