ジョギング
- おやすみ
日課
- おやすみ
東京出張
- 武川さんと色々と話したり, 計画作業を 2 件こなしたり
- 大住さんと新橋の立ち呑み屋さんで色々と話しが出来てよかった
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (44) ~
REx - Ruby Examination の問題を自分なりにアレンジした上で 1 〜 3 問くらいずつ解いていく. 正直言ってかなり難しい. 尚, irb に動作確認環境は以下の通り.
$ ruby --version ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux] $ irb --version irb 0.9.6(09/06/30)
文法 (論理演算子)
以下のコードを実行するとどうなるか.
v1 = 1 / 2 == 0 v2 = !!v1 or raise RuntimeError puts v2 and false
以下, 解答.
true が表示される
以下, irb にて確認.
irb(main):001:0> v1 = 1 / 2 == 0 => true irb(main):002:0> v2 = !!v1 or raise RuntimeError => true irb(main):003:0> puts v2 and false true => nil
以下, 解説より抜粋.
- 1 行目では
Fixnum
クラス同士の除算はFixnum
クラスとなり,0 == 0
が評価されtrue
となる - 2 行目の
or
では左辺が真であれば, 右辺は評価されず, 左辺の結果が返る !!v1
は否定 (!
) の否定 (!
) となる為,true
となり, 左辺がtrue
となっているのでv2
にはtrue
が代入される- 3 行目の
and
は左辺が真であれば, 右辺の結果を返し, 左辺が偽であれば左辺の結果を返すが,and
は優先度が低い演算子である為,puts v2
が評価される
and, or, not の優先度
以下, &&
と and
の違い.
# p (1 && 2) と同義 irb(main):006:0> p 1 && 2 2 => 2 # p (1) and 2 と同義 irb(main):007:0> p 1 and 2 1 => 2
以下のように and
を利用する場合, 二重括弧を利用することで, &&
と同等の結果を得ることが出来る.
irb(main):008:0> p (1 && 2) 2 => 2 irb(main):009:0> p ((1 and 2)) 2 => 2
or
は, 左辺を評価して結果が真であった場合にはその値を返し, 左辺の評価結果が偽であった場合には右辺を評価してその評価結果を返す. or
についても and
と同様に p false
の実行結果と true
が評価される (or
の優先度が低い)為, 以下のような結果となる.
irb(main):019:0> p false || true true => true irb(main):020:0> p false or true false => true
not
は, 式の値が真である時には 偽
を, 偽であるには真を返す.
irb(main):024:0> p ! true false => false irb(main):025:0> p not true SyntaxError: (irb):25: syntax error, unexpected keyword_true, expecting '(' irb(main):028:0> p (! false) true => true irb(main):030:0> p ((not false)) true => true
Enumerable と Enumerator
次のプログラムを実行するために __(1)__ に適切なメソッドをすべて選ぶ.
class IPAddr include Enumerable def initialize(ip_addr) @ip_addr = ip_addr end def each return __(1)__ unless block_given? @ip_addr.split('.').each do |octet| yield octet end end end addr = IPAddr.new("192.10.20.30") enum = addr.each p enum.next # 192と表示される p enum.next # 10と表示される p enum.next # 20と表示される p enum.next # 30と表示される
以下, 解答.
to_enum enum_for
以下, irb にて確認.
irb(main):001:0> class IPAddr irb(main):002:1> include Enumerable irb(main):003:1> irb(main):004:1* def initialize(ip_addr) irb(main):005:2> @ip_addr = ip_addr irb(main):006:2> end irb(main):007:1> irb(main):008:1* def each irb(main):009:2> return to_enum unless block_given? irb(main):010:2> irb(main):011:2* @ip_addr.split('.').each do |octet| irb(main):012:3* yield octet irb(main):013:3> end irb(main):014:2> end irb(main):015:1> end => :each irb(main):016:0> irb(main):017:0* addr = IPAddr.new("192.10.20.30") => #<IPAddr:0x005611774ad498 @ip_addr="192.10.20.30"> irb(main):018:0> enum = addr.each => #<Enumerator: #<IPAddr:0x005611774ad498 @ip_addr="192.10.20.30">:each> irb(main):020:0> enum.next => "192" irb(main):021:0> enum.next => "10" irb(main):022:0> enum.next => "20" irb(main):023:0> enum.next => "30" irb(main):001:0> class IPAddr irb(main):002:1> include Enumerable irb(main):003:1> irb(main):004:1* def initialize(ip_addr) irb(main):005:2> @ip_addr = ip_addr irb(main):006:2> end irb(main):007:1> irb(main):008:1* def each irb(main):009:2> return enum_for unless block_given? irb(main):010:2> irb(main):011:2* @ip_addr.split('.').each do |octet| irb(main):012:3* yield octet irb(main):013:3> end irb(main):014:2> end irb(main):015:1> end => :each irb(main):016:0> irb(main):017:0* addr = IPAddr.new("192.10.20.30") => #<IPAddr:0x0055afc3901730 @ip_addr="192.10.20.30"> irb(main):018:0> enum = addr.each => #<Enumerator: #<IPAddr:0x0055afc3901730 @ip_addr="192.10.20.30">:each> irb(main):019:0> enum.next => "192" irb(main):020:0> enum.next => "10" irb(main):021:0> enum.next => "20" irb(main):022:0> enum.next => "30"
以下, 解説より抜粋.
- Enumerable をインクルードした場合,
each
メソッドを実装する必要があり, ブロックが渡されない場合でも, Enumerator オブジェクトを返すようにして外部イテレータとしても使えるようにする - Enumerator オブジェクトを作成するメソッドは
enum_for
, またはto_enum
を利用する
フムフム.