Ruby Gold模擬試験誤答一覧

あと試験日まで17日にして52/100点というものすごい点数をたたき出しているorz それでも前回の40/100点よりよくなっているのか....

それにしてもRExの問題は模擬試験よりだいぶ難しく作られているように感じる。

問題2: Float, Rational, Complex同士の計算

FloatとFixnum同士の計算はFixnumで、より精度の細かいほうで答えが返される。 また、RationalとComplex同士の計算はComplexで返される。(Complexの方は他の表現方法がないので、これはわかりやすい。)

irb(main):005:0> (1/3r + 2i).class
=> Complex  

しかし、FloatとRational同士の計算の答えは、Floatが返される。 これはRationalの方がより正確であることを考えれば、やや不自然な挙動に感じる。

irb(main):002:0> b = 1/3r
=> (1/3)
irb(main):003:0> b + 0.05
=> 0.3833333333333333

問題3: when-caseの比較

case文の比較には===という特別なメソッドが用いられる。

===というメソッドは左辺に持ってくるオブジェクトごとに再定義が可能なので、左辺のオブジェクトごとの===メソッドのオーバーライドを知っておかないと挙動を把握できない。

問題9: 組み込み定数

はじめて聞く名前だったが、「実行環境」の章で扱っていたようだった。 全てがObjectクラスに所属しているという解釈で良いようだ。

名前 意味
STDIN 標準入力
STDOUT 標準出力
STDERR 標準エラー出力
ENV 環境変数
ARGF 仮想ファイル
ARGV 実行引数
DATA END以降の文字列

問題10: rescue節での再raise

rescue節での再raiseは救出した例外を再度発生させる。

問題11 : DATA & END

問題10で扱ったばかりだが、DATAはファイルのEND以降をオブジェクトとして扱うための定数である。

問題12 : alias 新名 旧名

メソッド名の変更には以下の2つの方法がある。

alias

新メソッド名 replace 旧メソッド名 の並び方。 文字列で表記する必要はなく、リテラル(そのまま)かシンボルで指定する。

命名変更後は、変更対象のメソッドが再定義されても、変更は適用されない。(つまり命名変更を行った時点から動きが変わらない。) 変更を適用したい場合、新メソッド名で再定義を行う必要がある。

alias_method

Kernel moduleのメソッド。こちらは、シンボルか文字列で定義をし直す。 KErnel moduleのスコープに入って利用する必要があるため、あんまり使われ無さそう。

問題13: クラス変数

クラス変数は特異クラスからもクラスのクラス変数にアクセス出来てしまう。 よって、特異クラスで定義されている特異メソッドからも一番最後に更新されたクラス変数が更新される。

問題17: undef

クラス/メソッドの定義 (Ruby 2.6.0)

ここにズバリが書いてあって、undefはスーパークラスに対しても効果を発揮する。 なお、undefに指定するメソッド名はリテラル(そのまま)かシンボルを用いる。

問題18: 多重代入(配列)

配列展開*がないと代入されないもんだと思っていたら、そうでもなかった。

irb(main):005:0> a,b,c = [1,2,3]
=> [1, 2, 3]
irb(main):006:0> p a
1
=> 1
irb(main):007:0> p b
2
=> 2
irb(main):008:0> p c
3
=> 3
irb(main):009:0> a,b,c = 1,2,3
=> [1, 2, 3]
irb(main):010:0> p a
1
=> 1
irb(main):011:0> p b
2
=> 2
irb(main):012:0> p c
3
=> 3

数が足らなくても、出来ちゃう

irb(main):006:0> a,b,c,d = [1,2]
=> [1, 2]
irb(main):007:0> p a
1
=> 1
irb(main):008:0> p b
2
=> 2
irb(main):009:0> p c
nil
=> nil

代入される側が足らなくてもOK!

irb(main):010:0> e,f = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):011:0> p e
1
=> 1
irb(main):012:0> p f
2
=> 2

問題19: 昇順・降順

昇順にしたい場合は、右側にくる値が「1」か引き算をして正の値がでればよい。

pyons@LAPTOP-SF87NLCB:/mnt/c/Users/broad$ irb
irb(main):001:0> x = ['AAAAA','CCC','BBBB']
=> ["AAAAA", "CCC", "BBBB"]
irb(main):002:0> x.sort{|x,y| x.size - y.size}
=> ["CCC", "BBBB", "AAAAA"]
irb(main):004:0> x.sort{|x,y| x.size <=>  y.size}
=> ["CCC", "BBBB", "AAAAA"]
irb(main):005:0> x.sort{|x,y| y.size <=>  x.size}
=> ["AAAAA", "BBBB", "CCC"]
irb(main):006:0> x.sort{|x,y| y.size -  x.size}
=> ["AAAAA", "BBBB", "CCC"]

問題24: StringIO

StringIOに関しては既に他の投稿でカバーしている。

1: 文字列をIOオブジェクトと同じように扱える。

IOクラスについて完全に忘れているが、IOクラスはFileクラスのスーパークラスで、標準出力、標準入力、標準エラー出力を扱うためのクラスである。ファイルの位置のポインタを指定して読み込んだり、ポインタの位置をファイルの先頭にするためのオプション定数が存在したするあたりは、IOオブジェクトに似ている。

実際StringIOは「文字列をIOオブジェクトのように扱う」ことを目的に作られた添付ライブラリである旨が教科書でも述べられている。

2 : ファイル入出力専用の文字列である。

それはおそらくIOクラスのことを指している。

3 : IOクラスのサブクラスである。

IOクラスと同じようなインターフェースを持っている旨が述べられているが、IOクラスと直接の継承関係はない。IOクラスは ObjectクラスのDataクラスのサブクラスである。

一方のIOクラスはObjectクラス直下のクラスであり、そのサブクラスにFileの他Basic SocketというIPソケットなどのスーパークラスとなるクラスが継承されている。

4: 文字列をファイルに読み書きできる。

それはIOクラスの仕事。

よって答えは1のみとなる。

問題25: トップレベルに定義するメソッド

トップレベルに定義されたメソッドはObjectクラスのprivateメソッドとして定義される。

問題 29: 多重代入

既に取り扱ったが、配列の多重代入は展開して行われる。

問題 30: freeze

freezeはオブジェクトの変更自体を禁止するもので、「オブジェクトの自己代入」が行われてしまえば、もうその変数に代入されているオブジェクト自体が異なってしまうので、freezeの意味をなさない。

問題 33: undef

問題17と全く同じ。undefは継承関係を遡って適用される。

問題 34: Module#ancestors

ちょっとした引っ掛け問題。 ancestorsはクラスおよびモジュールがレシーバーのときだけ使える。 今回はメソッドの中で利用なのでselfはオブジェクトになる。

問題 39: RDoc

別のポストでこれを中心に扱う。

問題41 : Data, DataTime, Time

Time以外はrequrieが必要。

irb(main):004:0> (Time.new - Time.new).class
=> Float
irb(main):013:0> require 'date'
=> true
irb(main):014:0> (DateTime.new - DateTime.new).class
=> Rational
irb(main):015:0> (Date.new - Date.new).class
=> Rational

問題 42: Fiber

Fiberオブジェクトは1回しかresumeされていないので、yieldで引数"B"を返した後の処理は行われない。

問題 43/45: freeze, dup, clone

freezeについての印象がやたらと薄く、なんでこんな印象薄いんだろうと思っていたら、1/3ページ分しか扱われていなかった。

1 : cloneはfreeze, taint, 特異メソッドなどの情報も含めて、完全な複製を作成する。 2 : dupはfreeze, taint, 特異メソッドなどの情報も含めて、完全な複製を作成する。

class C  
end

c = C.new
class << c  
  def method
    puts "method!"
  end
end
c.method # method!
d = c.clone
d.method # method!

少なくとも、特異メソッドはちゃんとコピーされた。 でもdupは特異メソッドはコピーされない。

class C
  attr_accessor :variable 
  def initialize
    @variable = 100
  end
end

c = C.new
class << c  
  def method
    puts "method!"
  end
end

c.method # method!
d = c.dup
d.method

cloneは特異メソッドとtaintとfreezeも含めてコピーされるが、 dupは特異メソッドとfreezeはコピーされず、taintのみがコピーされる。

クラスだけでなく、モジュールもfreeze可能である。

モジュールをincludeしたクラスをfreezeすることは出来ない。

どちらも×で、モジュールだろうがクラスだろうがfreezeすることが可能である。

参照先のオブジェクトもコピーされる。

Rubyにはdeep copyの機能がない」ことをマーシャルで取り扱ったが、cloneについても例外ではなく、浅いcopyしかできない。

問題 47: Marshalが出来ない条件

マーシャルについて扱った章の冒頭に書いてあった。忘れていただけ。

  • 名前のついていないクラスやモジュール

  • File, Dir, IOなどシステムがオブジェクトの状態を保持するもの

  • MatchData, Proc, Threadクラスのインスタンス

  • 特異メソッドが定義された、インスタンス

問題 49: load & require

loadは拡張子の補完を行わず、複数回のロードも可能である。バイナリエクステンションはロードできない。 requireは拡張子の補完を行い、複数回のロードを防ぐ。バイナリエクステンションのロードも可能である。

問題50: Threadの例外

Thread内で例外が発生しても、他のスレッドが(sleepしているスレッドが)生き続けている限り、プログラム自体の終了にはならない。また、エラーメッセージの表示なども行われない。

但し、デバッグモードで実行している場合、実行しているいずれかのスレッドで例外が発生すればメッセージを表示して処理は終了となる