ようへいの日々精進XP

よかろうもん

2018 年 06 月 26 日 (火)

ジョギング

  • 自宅→香椎宮香椎浜で 35 分くらい
  • 左足足底筋の痛み
  • 蒸し暑い
  • 明日は休もうかな...

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

体調

  • 悪し
  • 暑さにやられた感がある

今日のるびぃ ~ REx - Ruby Examination にチャレンジ (38) ~

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)

正規表現

以下のコードを実行するとどうなるか.

p "This is a aPPle"[/[a-z][A-Z].*/]

以下, 解答.

aPPle が表示される

以下, irb にて確認.

irb(main):017:0> p "This is a aPPle"[/[a-z][A-Z].*/]
"aPPle"
=> "aPPle"

以下, 解説より抜粋.

  • スラッシュ / で囲まれた文字列は正規表現と扱われる
  • 設問では, 文字列から String#[]正規表現を用いて部分文字列を抜き取る
  • 設問の正規表現 /[a-z][A-Z].*/ を分解すると以下のような意味となる
    • [a-z]: 1文字目が小文字英字
    • [A-Z]: 2文字目が大文字英字
    • .*: 任意の1文字が0回以上繰り返す

Regexp#match

Regexp#match を試す.

指定された文字列 str に対して位置 pos から自身が表す正規表現によるマッ チングを行います。マッチした場合には結果を MatchData オブジェクトで返し ます。 マッチしなかった場合 nil を返します。

irb(main):022:0> p "This is a aPPle".match(/[a-z][A-Z].*/)
#<MatchData "aPPle">
=> #<MatchData "aPPle">

正規表現にマッチした部分文字列だけが必要な場合, 以下のように書くことで取得出来る.

irb(main):023:0> bar = /foo(.*)baz/.match("foobarbaz")
=> #<MatchData "foobarbaz" 1:"bar">
irb(main):024:0> bar = /foo(.*)baz/.match("foobarbaz").to_a[0]
=> "foobarbaz"
irb(main):025:0> bar = /foo(.*)baz/.match("foobarbaz").to_a[1]
=> "bar"
irb(main):027:0> /(foo)(bar)(baz)/.match("foobarbaz").to_a.values_at(1,2,3)
=> ["foo", "bar", "baz"]

String#[]

String#[] を試す.

nth 番目の文字を返します。 nth が負の場合は文字列の末尾から数えます。 つまり、 self.size + nth 番目の文字を返します。 nth が範囲外を指す場合は nil を返します。

irb(main):029:0> 'bar'[-1]
=> "r"
irb(main):030:0> 'bar'[0]
=> "b"
irb(main):031:0> 'bar'[1]
=> "a"
irb(main):032:0> 'bar'[2]
=> "r"

正規表現 regexp の nth 番目の括弧にマッチする最初の部分文字列を返します。 nth を省略したときや 0 の場合は正規表現がマッチした部分文字列全体を返します。 正規表現が self にマッチしなかった場合や nth に対応する括弧がないときは nil を返します。

このメソッドを実行すると、 マッチ結果に関する情報が組み込み変数 $~ に設定されます。

irb(main):037:0> 'foo bar baz'[/f.o/]
=> "foo"
irb(main):038:0> $~
=> #<MatchData "foo">
irb(main):039:0> $~.to_a
=> ["foo"]

Object クラス

以下のコードを実行するとどうなるか.

class Object
  CONST = "1"
  def const_succ
    CONST.next!
  end
end

class Child1
  const_succ
  class << self
    const_succ
  end
end

class Child2
  const_succ
  def initialize
    const_succ
  end
end

Child1.new
Child2.new

p Object::CONST

以下, 解答.

5 が表示される

以下, irb による確認.

irb(main):001:0> class Object
irb(main):002:1>   CONST = "1"
irb(main):003:1>   def const_succ
irb(main):004:2>     CONST.next!
irb(main):005:2>   end
irb(main):006:1> end
=> :const_succ
irb(main):007:0> 
irb(main):008:0* class Child1
irb(main):009:1>   const_succ
irb(main):010:1>   class << self
irb(main):011:2>     const_succ
irb(main):012:2>   end
irb(main):013:1> end
=> "3"
irb(main):014:0> 
irb(main):015:0* class Child2
irb(main):016:1>   const_succ
irb(main):017:1>   def initialize
irb(main):018:2>     const_succ
irb(main):019:2>   end
irb(main):020:1> end
=> :initialize
irb(main):021:0> 
irb(main):022:0* Child1.new
=> #<Child1:0x0056408aab6190>
irb(main):023:0> Child2.new
=> #<Child2:0x0056408aaae990>
irb(main):024:0> 
irb(main):025:0* p Object::CONST
"5"
=> "5"

以下, 解説より抜粋.

  • Object クラスにメソッドを定義すると特異クラスでもそのメソッドを利用することが出来る
  • Object#const_succ について, 内部で String#next! を実行している為, レシーバーの文字列を次の文字列へ進める

以下, クラス定義毎に Object::CONST の値を確認.

irb(main):001:0> class Object
irb(main):002:1>   CONST = "1"
irb(main):003:1>   def const_succ
irb(main):004:2>     CONST.succ!
irb(main):005:2>   end
irb(main):006:1> end
=> :const_succ
irb(main):007:0> p Object::CONST
"1"
=> "1"
irb(main):008:0> class Child1
irb(main):009:1>   const_succ
irb(main):010:1>   class << self
irb(main):011:2>     const_succ
irb(main):012:2>   end
irb(main):013:1> end
=> "3"
irb(main):014:0> p Object::CONST          
"3"
=> "3"
irb(main):015:0> class Child2
irb(main):016:1>   const_succ
irb(main):017:1>   def initialize
irb(main):018:2>     const_succ
irb(main):019:2>   end
irb(main):020:1> end
=> :initialize
irb(main):021:0> p Object::CONS                       
"4"
=> "4"
irb(main):022:0> Child1.new
=> #<Child1:0x0056352f061778>
irb(main):023:0> p Object::CONST
"4"
=> "4"
irb(main):026:0> Child2.new                        
=> #<Child2:0x0056352ef600b8>
irb(main):027:0> p Object::CONST
"5"
=> "5"

また, Object クラスではなく, 任意のクラス (Foo) を定義した場合の挙動を確認.

irb(main):001:0> class Foo
irb(main):002:1>   CONST = "1"
irb(main):003:1>   def const_succ
irb(main):004:2>     CONST.next!
irb(main):005:2>   end
irb(main):006:1> end
=> :const_succ
irb(main):010:0> class Bar
irb(main):011:1>   class << self
irb(main):012:2>     const_succ
irb(main):013:2>   end
irb(main):014:1> end
NameError: undefined local variable or method `const_succ' for #<Class:Bar>
...

上記のように, 特異メソッドを定義しようとしても例外となる.

フムフム.