instance_methods(true)
は何を返しますかrand
がいつも同じ乱数列を出しますがFixnum
、Symbol
、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 end
Dir.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)
あります。次のような構文を使います。
begin (例外が発生しそうな処理) rescue (例外クラス) (例外が発生した場合の処理) else (例外が発生しなかった場合の処理) ensure (必ず実行したい処理) end
begin
節で例外が発生するとrescue
節が実行されます。
例外が発生しなければelse
が実行されます。
ensure
節は例外が発生してもしなくても必ず実行されます。rescue
,
else
,ensure
節はそれぞれ省略できます。
rescue
の後ろに例外クラスが
指定されなかった場合は
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を作れます。 (ただし、この場合ハッシュのキーと値は文字列に限定されます)
以下のコードは、バージョン 1.4 以前には rescue 節がちゃんと実行されて いましたが、バージョン 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>
なお、バージョン 1.7 では NameError クラスは StandardError のサブクラスに 戻っています。どの例外がデフォルトで捕捉できるかは 例外クラス で、クラス階層を確認してください。
Integer#prev
は簡単に定義できます。しかしsucc
ほど有用とは思えません。
一方String#prev
はうまく定義できません。
例えば
'09'.succ == '9'.succ #=> true
というように、succ前と後の文字列が一対一対応でない場合があるため、
str.prev.succ == str.succ.prev
が必ずしも成立しないからです。
*1この項がFAQなのは引数の意味が昔リファレンスに載っていなかったためです
*2ruby 1.6 feature: true/false/nil に対しては version 1.6 からは定
義できます。