Ruby Gold基礎力確認問題 誤答一覧
問6: ブロック引数と引数の書き方
ブロック引数で{ }
を使った書き方をする場合は、ブロックに送る引数に()を省略することは出来ない。
これは、普段コードに見慣れているとなんとなくわかるが、
do..endでブロック引数を書く場合、ブロックに送る引数は()
を付けても、付けなくてもよい。
1.upto(5)do |x| puts x end 1.upto 5 do |x| puts x end 1.upto(5){ |x| puts x }
3つとも機能する。一番上の例は見慣れないけど、ちゃんと実行される。
問8: 可変長引数とキーワード引数
[1,2,3]という標準出力を期待するとき
def hoge(*args) p args end hoge [1,2,3] # [[1, 2, 3]] hoge *[1,2,3] # [1, 2, 3]
hogeの引数argsは配列であり、渡された引数を一要素ずつ配列として扱っていく。 よってargsをそのまま出力すれば、配列に入った配列が返ってくる。
一方、実引数の時点で*を付けてやると「配列展開」が行われ、配列の各要素はそれぞれ3つの別個の要素として、argsに渡される。 これにより、3つの別個の要素を配列に格納する。これにより、期待する出力が出せる。
配列展開はメソッド内で行っても良いので、以下のような書き方もできる。
def hoge(*args) p *args end hoge [1,2,3] # [1, 2, 3]
また、キーワード引数についても調べてみる。
def hoge(x:, y: 2, **params) puts params # {:a=>100, :z=>3} puts "#{x},#{y},#{params[:z]}" # 1,2,3 end hoge a:100, x:1, z:3
仮引数のは一番最後に置くことで、残りのキーワード引数をハッシュで受け取ってくれる。 hash_nameなのでhash_name[key]でキーワードを指定して値を取得することが出来る。
問9: キーワード引数
キーワード引数は本来、仮引数にキーワードを指定して使うものだが、任意のキーワードをハッシュ展開の形で受け取ることもできる。
def method(x:, y:, **params) p x p y p params p '-----' end method(**{x: 100,y: 100,d: 100, r: 700}) # ハッシュにして**で展開 method(:x => 100, :y => 900) # 指定なしのキーワード引数を省略 method(x:100, y: 200, **{:r => 1000}) # 一部だけハッシュにして展開 method() # key.rb:11:in `<main>': missing keywords: x, y (ArgumentError)
pyons@LAPTOP-SF87NLCB:/mnt/c/Users/broad/OneDrive/products/Ruby認定技術者試験Gold$ ruby key.rb "X: 100, Y: 100, params: {:d=>100, :r=>700}" "X: 100, Y: 900, params: {}" "X: 100, Y: 200, params: {:r=>1000}" key.rb:8:in `<main>': missing keywords: x, y (ArgumentError)
paramsのハッシュ展開をやめてみと、key.rb:1: syntax error, unexpected tIDENTIFIE
となる。
ハッシュ展開で引数を引き受けない限り、必ず引数が必要となる。
問13: self
インスタンス化されたクラスのクラス定義内で出てくるself
はインスタンスのself
であるという点に注意する必要がある。
メソッドが呼ばれると、「一歩右へ、それから上へ」の原則でメソッド探索を始めた後、該当のメソッドに到達すると呼び出しメソッドのレシーバーをsellfにして実行される。
module M puts self.class # Module def foo self.class end end class C include M end puts C.new.foo # C
レシーバーやクラス定義の内側のselfはクラスやモジュール自身となる。
よって、module内の標準出力はModule
となる。
問18: protected
protectedに設定されたメソッドは、レシーバーを付けても呼び出すことが出来る。ただし、(本体と継承先の)クラス定義内からの呼び出ししか受け付けない。priveteはクラス内部からの実行のみ受け付ける。
class Parent def self_call self.method1 end protected def method1 'protected method' end end p Parent.new.self_call # "protected method" p Parent.new.method1 # key.rb:21:in `<main>': protected method `method1' called for #<Parent:0x007fffba087408> (NoMethodError) class Child < Parent def call_from_childe self.method1 end end p Child.new.call_from_childe # "protected method"
問22: 正規表現と$記号
%r|(http://www(\.)(.*)/)| =~ "http://www.abc.com/" puts $0 # upto.rb (プログラム名) puts $1 # (http://www(\.)(.*)/)の部分: http://www.abc.com/ puts $2 # (\.)の部分: . puts $3 # (.*)の部分: abc.com
$nはn番目の括弧に対応する文字列を指しており、括弧が入れ子になっていても、正規表現マッチに対応する部分を取得できる。
問27: Socketライブラリにある全クラス
- UDPはソケットがソケットとサーバーを兼ねる。
- TCPにはソケットとサーバーが別クラスで用意されている。
- BasicScoektクラスはインターネット関連のソケット
IPSocket
とUNIXのプロセス間通信のサーバー側を担うUNIXSocket
とそのサーバー側となるSocket
クラスが継承される抽象クラスで、サーバー側のクラスもここから継承されている。よってBasicServer
クラスは存在しない。
問29: 標準添付ライブラリ全般
- StringIOはIOと同じインターフェースを持つ => Yes. そのためのStringIO. ただし、直接の継承関係はなし。
- FloatとRationalの演算結果はFloat => Yes. その分、精度が下がってしまいそうだが、そういう仕様なので。
- rdocは
*
において番号付きリストを作る。 => No.# 1. List 1 # 2. List 2
で作る。数字の後にコンマが必要。 - Treadのstart, fork, runはいずれも新しいスレッドを作る。 => No,
new, start, fork
が正解。run
はwakeup
とともに再開用。 - DateTimeに1足すと翌日になる。=> Yes. 因みにDataもなる。
問30: open-uriクラス
もはや教科書で扱われてすらいなかった。なんで載せたんだよ...
library open-uri (Ruby 2.6.0 リファレンスマニュアル)
Karnel#openの再定義を行うようだ。普段はIO
かFile
のクラスメソッドとして使われていて、単独で使うことはないが、このモジュールが可能にしている。