前のページ 次のページ 目次

6. クラスライブラリ

6.1 シンボルから値を取り出すにはどうすればいいですか

symbolのスコープでeval((:symbol).id2name)とすると,値が取り出せます.

a = 'This is the content of "a"'
b = eval(:a.id2name)
a.id == b.id

6.2 loopは制御構造ですか

メソッドです.ブロックは新しいローカル変数のスコープを導入します.

6.3 instance_methods(nil)は何を返しますか

instance_methodsは,あるクラスのオブジェクトが持つメソッドを返しますが, instance_methods(nil)は,スーパークラスから引き継いだものではなく,その クラスで初めて定義されたメソッドを返します.

6.4 nilfalseはどう違いますか

持っているメソッドの違いは,nil.methods - false.methodsfalse.methods - nil.methodsを表示してください.

ハッシュでは,nilを値として持つことができませんが, falseを持つことはできます.

?のつくメソッドは,真偽を返す場合はtruefalseを, そうでない時は値もしくはnilを返します.

6.5 ファイルを書き換えても変化しません

open("example", "w+").readlines.each_with_index{|l, i|
  l[0,0] = (i+1).to_s + ": "}
とやっても,exampleに行番号がつきません. ファイルを書き換えているのではなく,readlinesで読み込んだ文字列を変えて いるだけです.ファイルに書き戻してやらなければいけません.

io = open("example", "w+")
ary = io.readlines
ary.each_with_index{|l, i| l[0,0] = (i+1).to_s + ": "}
io.rewind
io.print ary
io.close

6.6 ファイルを時間の新しい順にソートしたいのですが

Dir.glob("*").filter{|f| [File.mtime(f), f]}.
  sort{|a,b| b[0]<=>a[0]}.filter{|e| e[1]}
とすると,カレントディレクトリの".",".."以外のファイルを更新時間の 新しい順にソートした配列を返します.

6.7 ファイルの行数を数えたいのですが

ファイルの最後にも改行があるものと仮定して,次のが一番速いでしょう.

open("file").read.delete("ˆ\n").size

6.8 :exitというのは何ですか

シンボルと呼ばれる,識別子と1対1対応する整数(Fixnum)です.

6.9 英語文字列の配列を辞書順にソートしたいのですが

ary.filter{|f| [f.downcase, f]}.sort.filter{|e| e[1]}
とします.downcaseで等しくなった場合に,元の文字列で比較を行うのが tipsです.

6.10 文字列から1文字ずつ文字列を取り出すにはどうしますか

split(//)やscan(/./)を使います.

6.11 "abcd"[0]は,何を返しますか

文字aのコード97(Fixnum)を返します.これが文字aと一致するかどうか 調べるには,?aと比較します.

6.12 タブをスペースに展開したいのですが

aに展開したい文字列があるとして,次のどちらかを使えばいいでしょう.

1 while a.sub!(/(^[^\t]*)\t(\t*)/){$1+' '*(8-$1.size%8+8*$2.size)}

1 while a.sub!(/\t(\t*)/){' '*(8-$~.begin(0)%8+8*$2.size)}

6.13 バックスラッシュをエスケープするにはどうしますか

Regexp.quote('\\')で,エスケープされます.

gsubを使う場合には,gsub(/\\/, '\\\\')では,置換文字列が構文解析で 一度'\\'に変換され,実際に置き換えるときにもう一度'\'と 解釈されるので, gsub(/\\/, '\\\\\\')とする必要があります.\&がマッチ文字列をあらわす ことを使えば,gsub(/\\/,'\&\&')と書けます.

gsub(/\\/){'\\\\'}とブロックを使う形にすれば,エスケープが1回しか 解釈されませんので,求める結果が得られます.

6.14 '\1''\\1'はどう違いますか

同じです.シングルクォートの中では,\'\\だけが解釈され,それ 以外は解釈されません.

6.15 subsub!はどう違うのですか

subの場合はレシーバの状態は変化せず,コピーにsubが施されます.

sub!ではレシーバそのものが変更されます.

sub!のようにレシーバの状態を変化させるメソッドを破壊的メソッドと 呼びます.Rubyでは同名のメソッドで破壊的なものとそうでないものがある場 合,破壊的なメソッドには慣例的に!をつけます.

def foo(str)
    str = str.sub(/foo/, "baz")
end

obj = "foo"
foo(obj)
print obj
# -> "foo"

def foo(str)
    str = str.sub!(/foo/, "baz")
end

foo(obj)
print obj
# -> "baz"
sub!のように破壊的なメソッドは予期しない効果をもたらすことがある ので,使用する場合は十分注意してください.

6.16 範囲オブジェクトのコンストラクタ.....はどう違いますか

..は終端を含み,...は終端を含みません.

6.17 関数ポインタはありますか

Proc.newproclambdaでProcオブジェクトを作れば, 関数ポインタのような働きをさせることができます.

6.18 threadforkはどう使い分けるのですか

thread/forkはそれぞれ以下のような特徴を持っています.

一般にforkthreadを混ぜるのはよくないようです.

あと,Rubyのthreadはタイムシェアリング方式なので,threadを使 うことによって処理が速くなることはありません.

6.19 Marshalの使い方を教えてください

オブジェクトをファイルや文字列に格納しておき,後で再生できる ようにするものです.格納は

Marshal.dump obj, io, lev
という形式で行います.ioには書き込み可能なIOオブジェクト,levは オブジェクトが内容として他のオブジェクトを持っている時に,どこ までオブジェクトの内容を格納するかを決めます.lev段までオブジェクト をdumpしてもまだオブジェクトがある時には,そのオブジェクトのdumpは オブジェクトの参照になりますので,再生した時には,参照が変わって いるでしょうから,再生できないことになります.levのデフォルトは 100になっています.ioを省略した時には,文字列でdumpされます.

再生は

obj = Marshal.load io
または,

obj = Marshal.load str
という形式で,ioはdumpしたファイルを読み込み可能でopenしたもの, strはdumpした文字列を指定します.

6.20 例外処理はありますか

他の先進的な言語と同様にRubyも例外処理をサポートします.

begin
  (例外が発生しそうな処理)
rescue (例外クラス)
  (例外が発生した場合の処理)
ensure
  (必ず実行したい処理)
end

begin節で例外が発生するとrescue節が実行されます. ensure節は例外が発生してもしなくても必ず実行されます.rescueensureは省略できます.rescureの後ろに例外クラスが 指定されなかった場合は StandardErrorが指定されたものとみなされ,StandardErrorの サブクラスである例外が捕捉されます.

この式の値は,begin節の値です.

もっとも最近起った例外はグローバル変数$!により参照できます. 発生した例外の種類は$!.typeにより調べることができます.

6.21 trapはどのように使いますか

trap("PIPE") {raise "SIGPIPE"}

6.22 Tkが動かないのですが

お使いのTkのバージョンが古い可能性があります.新しいものと交換してみて ください.

6.23 デバッガはありますか

あります.Rubyを次のように起動してください.

  ruby -r debug your_script


前のページ 次のページ 目次