instance_methods(true)は何を返しますかrandがいつも同じ乱数列を出しますがFixnum、true、nil、falseが即値だということですが、参照との違いは何ですかnilとfalseはどう違いますかlessに文字列を渡したのですが、表示されませんFileオブジェクトはどうなりますかcloseしないのは気持ちが悪いのですがtrueになります"abcd"[0]は、何を返しますかsubとsub!はどう違うのですか..と...はどう違いますかtrapはどのように使いますかinstance_methods(true)は何を返しますかklass.instance_methods は、あるクラス(またはモジュール)
klass で定義されたインスタンスメソッドだけを返しますが、
klass.instance_methods(true) は、
スーパークラスから引き継いだものも含めてすべてのインスタンスメソッドを返します。
(ただし、public メソッドのみ)
private_instance_methods、 protected_instance_methods の引数の意味も同様です。
randがいつも同じ乱数列を出しますがruby 1.4.2以前ではrandは、プログラムが実行される度に同じ乱数列を生成します。
異なる乱数列を生成させるためには、srandで毎回異なる乱数の
種を与えてやる必要があります。srandを引数なしで呼ぶと、その時の
時間を種にしますので、異なる乱数列を生成させることができます。
次のメソッドは、0からnまでの数の中からm個をランダムに選んだ配列を返します。
def sample(n, m)
if m.zero?
[]
else
s = sample(n-1, m-1)
t = rand(n+1)
s.concat s.include?(t) ? [n] : [t]
end
end
再帰形でなく書けば、次のとおりです。
def sample(n, m)
s = []
((n-m)...n).each do |j|
t = rand(j+2)
s.concat s.include?(t) ? [j+1] : [t]
end
s
end
true、nil、falseが即値だということですが、参照との違いは何ですか特異メソッドを定義できないという制限があります。 *2
また、同じ数を表わすFixnumのインスタンスは常に同じものになります ので、インスタンス変数を定義した場合には、それも同じものを示すことにな ります。
nilとfalseはどう違いますか持っているメソッドの違いは、nil.methods - false.methodsと
false.methods - nil.methodsを表示してください。
メソッドが真偽を返す時は、true、falseを、そうでない
時は値かnilを返すようにすることが好まれます。
?のつくメソッドは、真偽を返すのが一般的ですが、
そうでないものもあります(組込みでは nonzero? のみ)。
open("example", "r+").readlines.each_with_index{|l, i|
l[0,0] = (i+1).to_s + ": "}
とやっても、exampleに行番号がつきません。
ファイルを書き換えているのではなく、readlinesで読み込んだ文字列を
変えているだけです。ファイルに書き戻してやらなければいけません。
io = open("example", "r+")
ary = io.readlines
ary.each_with_index{|l, i| l[0,0] = (i+1).to_s + ": "}
io.rewind
io.print ary
io.close
この例の場合、ファイルサイズは増える方向なので問題ないのですが ファイルサイズが小さくなるような変更に対しては
io.flush io.truncate(io.pos)
を io.close の直前に実行する必要があります。
コマンドラインオプションの-i、もしくは、組込み変数$-i
に""を指定することにより、同じ名前のファイルに書き戻すことができます。
上の問題は、次のように書くことができます。
$ ruby -i -ne 'print "#$.: #$_"' example
元のファイルを残しておきたければ、-i.bakなどとしてください。
open('file', 'w').print "This is a file.\n"
system 'cp file copy'
とやったのでは、コピーする時にfileに内容がフラッシュされて
いません。きちんとcloseしてからコピーしましょう。
f = open('file', 'w')
f.print "This is a file.\n"
f.close
system "cp file copy"
lessに文字列を渡したのですが、表示されませんf = open '|less', 'w' f.print "abc\n"
とやっても、直ちに終了してしまい、lessで眺めることができません。
closeしてやると、そこでlessの終了を待ちます。
f = open '|less', 'w' f.print "abc\n" f.close
最初の行は、f = IO.popen 'less', 'w'としても同じ結果となります。
open("file").readというように参照されないFile
オブジェクトは、次のガーベッジコレクションでcloseされて
捨てられます。
closeしないのは気持ちが悪いのですが参照されなくなったFileオブジェクトは、GCで自動的にクローズ されますが、明示的にクローズするには、次の4つの構文から選んで下さい (コードの長さ順に並べました)。
File.foreach('filename') {|line| print line }
File.readlines('filename').each {|line| print line }
File.open('filename') {|f|
f.each {|line| print line }
}
begin
f = File.open('filename')
f.each {|line| print line }
ensure
f.close if f
endDir.glob("*").collect{|f| [File.mtime(f), f] }.
sort{|a,b| b[0]<=>a[0] }.collect{|e| e[1] }
とすると、カレントディレクトリの"."、".."以外のファイルを更新時間の 新しい順にソートした配列を返します。更新時間の古い順にソートする なら、sortの後ろのブロックはなしにしても、いいですね。
Dir.glob("*").sort{|a,b| File.mtime(b)<=>File.mtime(a)}
でもソートすることができますが、比較する度にファイルにアクセスして 更新時間を調べますので、ソートするのに時間がかかります。
この問題を解決するもう一つの方法に個々のファイルの更新時間を キャッシュするオブジェクトを用意する方法があります。
cache = {}
def cache.mtime(x)
self[x] ||= File.mtime(x)
end
Dir.glob("*").sort{|a,b| cache.mtime(b) <=> cache.mtime(a)}
cache = nil
また ruby 1.7 では前者の例を簡単に実行するためのメソッド Enumerable#sort_by が追加されています。
Dir.glob("*").sort_by {|f| File.mtime(f)}.reverse
ハッシュのデフォルト値に0を指定して、次のようにすることができます。
freq = Hash.new(0)
open("file").read.scan(/\w+/){|w| freq[w] += 1}
freq.keys.sort.each {|k| print k, "--", freq[k], "\n"}
trueになりますRubyでは、nilとfalseだけが偽で、それ以外はすべて真に
なります。文字列が空かどうかを知るには、""と比較、empty?を使う、
lengthを0と比較するなどの方法があります。
ary.collect{|f| [f.downcase, f]}.sort.collect{|e| e[1]}
とします。downcaseで等しくなった場合に、元の文字列で比較を行うのが
tipsです。
"abcd"[0]は、何を返しますか文字aのコード97(Fixnum)を返します。これが文字aと一致するかどうか 調べるには、?aと比較します。
以下のような定石があります。
# 非破壊的
def expand_tab( str )
str.gsub(/([^\t]{8})|([^\t]*)\t/n) { [$+].pack("A8") }
end
# 破壊的
def expand_tab!( str )
1 while str.sub!(/(^[^\t]*)\t(\t*)/) { $1 + ' ' * (8-$1.size%8+8*$2.size) }
end
# 破壊的 (2)
def expand_tab!( str )
1 while str.sub!(/\t(\t*)/) {' ' * (8-$~.begin(0)%8+8*$1.size) }
end
Regexp.quote('\\')で、エスケープされます。
gsubを使う場合には、gsub(/\\/, '\\\\')では、置換文字列が
構文解析で一度'\\'に変換され、実際に置き換えるときにもう一度'\'と
解釈されるので、
gsub(/\\/, '\\\\\\')とする必要があります。\&がマッチ文字列を
あらわすことを使えば、gsub(/\\/,'\&\&')と書けます。
gsub(/\\/){'\\\\'}とブロックを使う形にすれば、エスケープが1回しか
解釈されませんので、求める結果が得られます。
subとsub!はどう違うのですかsubの場合はレシーバの状態は変化しません。文字列のコピーが
作られ、それに置換がほどこされて(置換が必要なければそのまま)返されます。
sub!ではレシーバそのものが変更されます。変更がない時には
nilが返されます。
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!のように破壊的なメソッドは予期しない効果をもたらすことがある
ので、使用する場合は十分注意してください。
\Zは、文字列の最後の文字が\nでない時は文字列の末尾に、 \nのときはこの改行の前にマッチします。
\n に関らず、文字列の最後にマッチさせたい場合は \z を使います。
..と...はどう違いますか..は終端を含み、...は終端を含みません。
Proc.new、proc、lambdaでProcオブジェクトを作れば、
関数ポインタのような働きをさせることができます。
また、MethodオブジェクトやUnboundMethodオブジェクトも関数 ポインタに近いものです。
スレッドとプロセスのフォークにはそれぞれ以下のような特徴があります。
一般に、プロセスフォークとスレッドを混ぜて使うのはよくないようです。
またRubyのスレッドはタイムシェアリング方式なので、スレッドを使う ことによって処理が速くなることはまずありません。またユーザレベル スレッドなのでマルチプロセッサの恩恵も受けられません。
オブジェクトをバイト列に変換する (シリアライズ serialize する) ための ものです。オブジェクトをファイルに保存しておいて後から復活させたり、 ネットワーク経由で転送することができるようになります。例えばオブ ジェクトobjをバイト列にするには
Marshal.dump(obj)
とします。このメソッドは文字列を返すので、次のように普通にファイルを 使って書き込めます。
File.open('filename', 'w') {|f|
f.write Marshal.dump(obj)
}
このようにバイト列化したオブジェクトをファイルに書き込むことはよく あるので、以下のような簡約表現も用意されています。
Marshal.dump(obj, io)
ioには書き込み可能なIOオブジェクトです。またこの形式だと大きなオブ ジェクトをバイト列化するときでも巨大な文字列を作らずに済みます。
一方、バイト列化したオブジェクトを再生するには次のようにします。 まずは文字列から戻す場合です。
obj = Marshal.load(str)
以下はIOオブジェクトから直接戻す倍です。
obj = Marshal.load(io)
他の先進的な言語と同様にRubyも例外処理をサポートします。
begin (例外が発生しそうな処理) rescue (例外クラス) (例外が発生した場合の処理) else (例外が発生しなかった場合の処理) ensure (必ず実行したい処理) end
begin節で例外が発生するとrescue節が実行されます。
例外が発生しなければelseが実行されます。
ensure節は例外が発生してもしなくても必ず実行されます。rescue,
else,ensure節はそれぞれ省略できます。
rescureの後ろに例外クラスが
指定されなかった場合は
StandardErrorが指定されたものとみなされ、StandardErrorの
サブクラスである例外が捕捉されます。
この式の値は、ensure 節を実行する直前の値です。
最後に起こった例外はグローバル変数$!により参照できます。
発生した例外の種類は$!.classにより調べることができます。
trapはどのように使いますか以下により、シグナル SIGPIPE が発生するとブロックが実行されます (そして、例外が発生します)。
trap("PIPE") {raise "SIGPIPE"}
ファイルの最後にも改行があるものと仮定すれば、次の方法が一番簡単でしょう。
open("filename").read.count("\n")
array という配列があった場合、
h = Hash[*array]
とすれば、array の奇数番目の値をキー、偶数番目の値を値とした h というハッシュが作られます。このとき array の要素は偶数個 でなければいけません。
array = [1,2,3,4]
h = Hash[*array]
p h
=> {1=>2, 3=>4}
なお、arrayの前の「*」は、メソッド呼び出しのところで紹介されている、 引数の展開用の記号です。
Arrayのように直接Hashを作るリテラルはありません。 そのかわり、
p h = Hash[*%w(1 foo 2 bar)]
=> {"1"=>"foo", "2"=>"bar"}
などと、いったんArrayを作るようにすれば、そこから簡単にHashを作れます。 (ただし、この場合ハッシュのキーと値は文字列に限定されます)
以下は、昔(version 1.4以前)は rescue 節がちゃんと実行されていましたが、 version 1.6 ではできなくなっています。
begin foo rescue puts "TRAP : #$!" end -:2: undefined local variable or method `foo' for #<Object:0x401bece0> (NameError) ruby 1.6.7 (2002-03-20) [i586-linux]
これは、例外クラス NameError が StandardError のサブクラス
ではなくなったためです(例外クラスを指定しない rescue は
StandardError 配下の例外クラスだけを捕捉します)。
ですので、このような場合は明示的に NameError を指定する必要があります。
begin foo rescue NameError puts "**TRAP** : #$!" end ruby 1.6.7 (2002-03-20) [i586-linux] **TRAP** : undefined local variable or method `foo' for #<Object:0x401bece0>
なお、version 1.7 での NameError クラスは StandardError のサブクラスに 戻っています。どの例外がデフォルトで捕捉できるかは 例外クラス で、クラス階層を確認してください。
Integer#prevは簡単に定義できます。しかしsuccほど有用とは思えません。
String#prevをstr.prev.succ == str.succ.prevとすると
'09'.succ == '9'.succ #=> true
のような場合に一意に定義できないという問題もあります。
*1この項がFAQなのは引数の意味が昔リファレンスに載っていなかったためです
*2ruby 1.6 feature: true/false/nil に対しては version 1.6 からは定
義できます。