sicpばかりしてたら、rubyのコードが書きたくなった。

「def esub! args new_syms」と書いたときのエラーに素で驚いた。

今回書いたコード

引数をとって一気にgsub!。*1

class String
  def esub! args, new_syms = nil
    if new_syms.nil?
      #argsがハッシュのとき
      regexps = args.keys.map {|e| Regexp.new e}
      new_syms = args.values
    else
      #argsが配列のとき
      regexps = args.map {|e| Regexp.new e}
    end
    
    regexps.inject(self) do |orig, change|
      # p orig
      edit_sym = new_syms.shift
      orig.gsub!(change) {edit_sym}
    end
  end

  def esub args, new_syms=nil
    dup.esub! args, new_syms
  end
end

def outputs target
  puts "元の文字列:    #{target}"
  puts "結果 :        #{yield(target)}" 
  puts "置換後の文字列: #{target}"
  puts
end

x="aiueo"
outputs(x) {|e| e.esub(%w{a i u e o}, %w{1 2 3 4 5})}
puts "==============="
outputs(x) {|e| e.esub!(%w{a i u e o}, %w{1 2 3 4 5})}

#hashも使えます
$KCODE='utf8'
y="今日は疲れました。ふとんでゆっくり寝たいです。"
h={"今日は" => "明日もきっと", "ました" => "ます。"}
outputs(y) {|e| e.esub(h)}

puts "==============="
#正規表現も使えます。
z= "a b cde 55 4 3 2"
outputs(z) {|e| e.esub(%w{\s+ \d+}, %w{(・_・), 44})}

結果

元の文字列:    aiueo
結果 :        12345
置換後の文字列: aiueo

===============
元の文字列:    aiueo
結果 :        12345
置換後の文字列: 12345

元の文字列:    今日は疲れました。ふとんでゆっくり寝たいです。
結果 :        明日もきっと疲れます。。ふとんでゆっくり寝たいです。
置換後の文字列: 今日は疲れました。ふとんでゆっくり寝たいです。

===============
元の文字列:    a b cde 55 4 3 2
結果 :        a(・_・),b(・_・),cde(・_・),44(・_・),44(・_・),44(・_・),44
置換後の文字列: a b cde 55 4 3 2

*1:respond_to? で分岐した方が良かったかもしれない