Hatena::ブログ(Diary)

Marginalia

2017-09-14

method_missing の謎(Ruby)

irb(main)> class A
irb(main)>   def method_missing(m, *args)
irb(main)>     p m
irb(main)>     p args
irb(main)>   end
irb(main)> end
=> :method_missing
irb(main)> b = A.new
=> #<A:0x00000001f18870>

irb(main)> b.nyao(:a)
:nyao
[:a]
=> [:a]
irb(main)> b.nyao = "pu"
:nyao=
["pu"]
=> "pu"

#よくわからないのはここから
irb(main)> b.nyao[:nu]
:nyao
[]
TypeError: no implicit conversion of Symbol into Integer
irb(main)> b.nyao[]
:nyao
[]
ArgumentError: wrong number of arguments (given 0, expected 1..2)
irb(main)> b.nyao[1, 2]
:nyao
[]
=> nil
irb(main)> b.nyao[1, 2, 3]
:nyao
[]
ArgumentError: wrong number of arguments (given 3, expected 1..2)

[] の使い方がよくわからない…

※参考
class BasicObject (Ruby 2.3.0)
 

ついでに

Ruby文字列リテラルを続けると、勝手に連結するらしい。

irb(main)> "aa" "bb" 'cc'
=> "aabbcc"

OpenStruct のコードリーディング(Ruby)

~/Documents/Ruby/コードリーディング/ostruct.rb の一部

class OpenStruct
  def initialize(hash=nil)
    #Hash{@table}
    @table = {}
    if hash
      hash.each_pair do |k, v|
        k = k.to_sym
        @table[k] = v
      end
    end
  end
  attr_reader :table
  
  def modifiable
    #@modifiable >> Hash{@table}
    begin
      @modifiable = true    #@modefiable は他に出てこない。
    rescue
      raise RuntimeError, "can't modify frozen #{self.class}", caller(3)
    end
    @table
  end
  protected :modifiable
  
  def new_ostruct_member(name)
    #String{name} -> Symbol{name} >> Symbol{name}
    name = name.to_sym
    unless singleton_class.method_defined?(name)    #特異メソッドが定義されていなければ定義する。Object#singleton_class
      define_singleton_method(name) { @table[name] }
      define_singleton_method("#{name}=") { |x| modifiable[name] = x }
    end
    name
  end
  protected :new_ostruct_member
  
  def method_missing(mid, *args)    # mid は呼び出しに失敗したメソッド名
    #Symbol{mid}, *args -> len, mname, err >> Object{args[0] or @table[mid]}
    len = args.length
    if mname = mid[/.*(?==\z)/m]    #「=」で終わる文字列のその前の部分を取り出す。正規表現の「(?=pat)」は「肯定先読み」なんだって。「m」は「.」が改行にもマッチするようにする。
      if len != 1
        raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)    #Kernel.#caller
      end
      modifiable[new_ostruct_member(mname)] = args[0]    #@table に args[0] を入れる。またそれが返り値。
    elsif len == 0
      if @table.key?(mid)
        new_ostruct_member(mid)
        @table[mid]
      end
    else
      err = NoMethodError.new "undefined method `#{mid}' for #{self}", mid, args
      err.set_backtrace caller(1)
      raise err
    end
  end
  
  def [](name)
    @table[name.to_sym]
  end
  
  def []=(name, value)
    modifiable[new_ostruct_member(name)] = value
  end
end

 
正規表現の「(?=pat)」については以下。
正規表現 (Ruby 2.3.0)
先読みを使ったパターン - 先読み - Ruby正規表現の使い方

2017-09-12

Ruby の Fiber

Fiber は結構複雑なのです。

Fiber.yield がなければ、Fiber は resume で呼び出される proc オブジェクトみたいなもの。ただし、1回しか呼び出せない。

f = Fiber.new do |st|
  st.upcase
end

p f.resume("tokyo")    #"TOKYO"
p f.resume("tokyo")    #a.rb:6:in `resume': dead fiber called (FiberError)

 
ブロック内(子)に Fiber.yield があるとそこで一旦処理が止まる。もう一度(親で)resume されると再開される。

f = Fiber.new do |st|
  puts "Kyoto"
  Fiber.yield
  st.upcase
end

f.resume("tokyo")    #"Kyoto"
p f.resume           #"TOKYO"

 
Fiber.yield で止まったあと、次の resume に引数があればそれが Fiber.yield の返り値になる。

f = Fiber.new do |st|
  puts "Kyoto"
  puts Fiber.yield
  st.upcase
end

f.resume("tokyo")      #"Kyoto"
p f.resume("Osaka")    #"Osaka", "TOKYO"      

 
Fiber.yield に引数があれば、resume の返り値になる。

f = Fiber.new do |st|
  puts "Kyoto"
  puts Fiber.yield("Nagoya")
  st.upcase
end

p f.resume("tokyo")    #"Kyoto", "Nagoya"
p f.resume("Osaka")    #"Osaka", "TOKYO"

 
ブロック内(子)と外(親)で、断続的に停止しながら通信できるのである。子で止まるときに親に通信できるし、親が再開させるときに子に通信できる。
 

途中で初期化されるフィボナッチ数列

f = Fiber.new do
  a, b = 0, 1
  loop do
    a , b = b, a + b
    x = Fiber.yield(a)
    a, b = 0, 1 if x
  end
end

ar = []
6.times {ar << f.resume(false)}
ar << f.resume(true)
6.times {ar << f.resume(false)}
p ar    #=>[1, 1, 2, 3, 5, 8, 1, 1, 2, 3, 5, 8, 13]

2017-09-11

Ruby の Gem メモ

salamander

タートルグラフィックス。
RubyGem 'Salamander' がようやく動いたよ - Marginalia
 

parallel

並列処理。
 

thor

Ruby でコマンドを作る。
Ruby の Thor でコマンドを作る - Marginalia
 

rubysdl

SDLRuby から使う。アクションゲームなどが作れたりする。
GitHub
 

gosu

アクションゲームを作る。
 

hashie

ハッシュの拡張。
 

awesome_print

p や pp のようにオブジェクトの内容をきれいに表示する。「require 'ap'」でいける。
見やすいprint - Qiita
 

ddp

これも p や pp の同類。オブジェクト継承関係やインスタンスメソッドを定義した行番号がわかる。
Data Printer gemを書いた。 - パルカワ2
Ruby の Object Data Dumper - 俺たちのブログ
 

pry

irb の強力版みたいなの。
Rubyistよ、irbを捨ててPryを使おう - TIM Labs

ローチケHMV(あるいはローソンWEB会員)のパスワード認証がアホなことに関して

どうでもいいことです。

大昔に「HMV」というサイトの会員になり、パスワードも登録しました。

そして、「HMV」は「ローチケHMV」になりました。

で、よく考えずに登録しておいたメルマガが鬱陶しいので、メルマガ配信を停止するよう、設定を変更しようとしました。
ローチケHMV」にログインし、パスワードが受理されました
どうやら設定の変更は「マイページ」で実行するになっているようなので、マイページに入ろうとしました。

そこで、再度のログイン要求されました。魚拓を見て下さい。よくわからないので、「ローソンWEB会員」のところにメールアドレスパスワードを打ち込んだところ、拒否されます。どうやらこれは、「ローチケHMV」のアカウントとはちがうようです(だって既にログインしているのですから)。

すると右下の方に「メルマガの変更・解除」があります。ははあ、これだなと思ってクリックしました。

するとまたメールアドレスパスワードの入力を求められたので、入力しました。しかし、受け付けてくれないのです。さらにわからなくなって、「​​パスワードをお忘れの方はこちら」をクリックしてみました。パスワードの変更をしようということです。

で、「パスワードをお忘れの方」のページでメールアドレス電話番号、生年月日を入力しました。すると、「会員登録されていないか、入力の内容に誤りがあります」と出ます。???です。

仕方がないので、また最初のログインページ(魚拓のページ)に戻って、そこで「※ パスワードをお忘れの方はこちら」をクリックしてみました。いわれたとおりメールアドレスと名前を入力し、送られてきたメールの URL をクリックしてパスワードを変更しました。

で、もう一度最初の「ローソンWEB会員」のところ(魚拓のページ)にメールアドレスと新しいパスワードを入力したところ、「現在の会員登録状態ではログインできません。恐れ入りますが、“こちら”からチケット予約に必要な情報を追加してください」と出ました。いろいろ入力させられました。

で、ようやく「マイページ」に入れて、メルマガ配信を停止する設定を行いました。


これでいいんだよね。いいかげんにしろ。これでメルマガ送信されてきたら怒るぞ。

無題

もちゃもちゃに絡まっている。自宅近所にて。