Ruby Tips!

RubyのTipsを紹介します

ファイル名を変更する

Rubyでファイル名を変更するには、File.renameまたはfileutilsライブラリのFileUtils.mvを使用する。これらはファイルを移動するメソッドである。引数には移動元のパス、移動先のパスを指定する。移動先のパスがディレクトリで既に存在する場合、ファイルはその下に移動される。

require 'fileutils'
File.rename('foo.txt', 'bar.txt')
FileUtils.mv('foo.txt', 'bar.txt')

この2つのメソッドの違いは、ファイルシステムを跨いだ移動ができるかどうかである。File.renameファイルシステムを跨げないが、FileUtils.mvファイルシステムを跨ぐことができる。

擬似的なキーワード引数を使う

このエントリではRuby 1.8と1.9で良く使われる擬似的なキーワード引数について説明する。Ruby 2.0にはキーワード引数が追加されたが、本エントリでは扱わない。

Rubyはキーワード引数をサポートしていないので、ハッシュをキーワード引数に見立てて使うことが良く行われる。呼び出されるメソッドはハッシュを受け取るように定義しておく。キーワード引数の解釈などはすべてメソッドの処理の中で行う。

def method(hash = {})
  p hash
end

このメソッドの呼び出しは以下のようにするのが一般的だ。Rubyではハッシュを1つ渡す場合はブレース{}を省略することができる。またRuby 1.9からはシンボルを使ったハッシュをさらに簡潔に書けるようになった。

method({:foo => 1, :bar => 2, :buz => 3})
method(:foo => 1, :bar => 2, :buz => 3)
method(foo:1, bar:2, buz:3) # Ruby 1.9のみ

文字列を文字ごとに繰り返す

Ruby 1.9ではString#each_charメソッドを使うと、文字列を文字ごとに繰り返すことができる。

"あいうabc".each_char{|c|
  puts c
}
=begin



a
b
c
=end

Ruby 1.8では文字列を文字ごとに繰り返すメソッドが用意されていない。以下のように、String#splitArray#eachを組み合わせるか、正規表現.が任意の1文字にマッチすることを利用してString#scanを使うと良い。

"あいうabc".split('').each{|c|
  puts c
}
=begin



a
b
c
=end
"あいうabc".scan(/./){|c|
  puts c
}
=begin



a
b
c
=end

ただしString#scanを使う方法では、.にマッチしない文字を取りこぼしてしまう事に注意。具体的には文字を成さないバイト列が含まれると、そのバイト列は無視される。

Rubyで複素数を扱う

Ruby複素数を扱うにはcomplexライブラリのComplexクラスを使う。Complexオブジェクトは、Kernel.#ComplexComplex.rectComplex.polerNumeric#to_cString#to_cなどを使って生成する。

require 'complex'
p Complex(1, 2) #=> (1+2i)
p Complex.rect(1, 2) #=> (1+2i)
p Complex.polar(2.23, 0.35 * Math::PI) #=> (1.0123988144191893+1.9869445489400601i)
p 1.to_c #=> (1+0i)
p "1+2i".to_c #=> (1+2i)

Complexクラスは四則演算が定義されているため、他の数値と同様に複素数との演算、他の数値との演算が可能である。複素数を含む演算の返却値はComplexオブジェクトとなる。

require 'complex'
c0 = Complex(1, 2)
c1 = Complex(3, 4)

p c0 + c1 #=> (4+6i)
p c0 - c1 #=> (-2-2i)
p c0 * c1 #=> (-5+10i)
p c0 / c1 #=> ((11/25)+(2/25)*i)

複素数から実部を得るにはComplex#realを使う。逆に複素数から虚部を得るにはComplex#imageを使う。また偏角Complex#argで得られる。

require 'complex'
c = Complex(1, 2)
p c.real #=> 1
p c.image #=> 2
p c.arg #=> 1.1071487177940904

古いメソッドを呼び出したら警告を表示する

プログラムの更新に伴って、呼び出しが推奨されない古いメソッドが生じることがあるかもしれない。そのようなメソッドは本来プログラム上から取り除くべきだが、いきなり取り除いてしまうと影響が大きいため、呼び出したら警告を表示するようにするのは良い妥協案だ。

Rubyでは特殊変数$VERBOSEでメッセージの警告レベルを管理している。この変数の値はコマンドラインオプション-W-v-wで変更可能である。この変数は警告レベルが低い順にnilfalse(デフォルト)、trueの値を取る。

古いメソッドを呼び出した時の警告は、この特殊変数$VERBOSEを参照して、警告レベルが高いときだけ表示するようにするとトラブルが少ないだろう。以下は警告レベルが最大の時に、警告のメッセージを出力するメソッドの例である。warnメソッドを使って標準エラー出力にメッセージを出力している。

def obsolete_method
  warn "obsolete_method is obsolete." if $VERBOSE

  # 処理
end

なおwarnメソッドは$VERBOSEnilの時にはメッセージを出力しないので、上記のコードでは$VERBOSEを二重にチェックすることになる。警告レベルが最大ではなく、デフォルト以上の場合にメッセージを表示したいのであれば、上記コードのif修飾子を削除すれば良い。

数値の絶対値を求める

Rubyで数値の絶対値を求めるにはNumeric#absを使う。
整数や浮動小数点数のほか複素数の絶対値もこのメソッドで求められる。

require 'complex'
p -1.abs #=> 1
p -1.0.abs #=> 1.0
p Complex(-1, -1).abs #=> 1.4142135623730951

ファイルの内容が同一かを比較する

2つのファイルの内容が同一かを比較したいのであれば、fileutilsライブラリのFileUtils.cmpメソッドが利用できる。このメソッドは引数で与えた2つのファイルの内容を比較し、同じであれば真を返す。自力でファイルを少しずつ読み込んで比較するよりも遥かに簡単である。

FileUtils.cmp('somefile', 'somefile') #=> true