2022/02/17 今回の気になった bugs.ruby のチケット

今週はパターンマッチの find 検索を正式に導入するチケットがありました。

[PR reline] Proposal for quick shell execution

  • irb. から始まるコマンドを入力した時に shell コマンドが実行されるようにする提案
  • pry だとこの機能が実装されているらしい
.cat .ruby-version
2.7.5
  • わたしは pry の機能を知らなかったんですが REPL で shell コマンドを実行したいときって結構あるんですかね
  • Ruby だと
`.cat .ruby-version`

[Bug #13885] Random.urandom と securerandom について

  • Random.urandomsecurerandom の仕様のチケット
  • チケット自体の内容よりも日本語で議論されていて普段どうやって議論されているのかがわかりやすいので気になる人は見てみるとよいかも

[Feature #18585] Promote find pattern to official feature

  • Ruby 3.0 で入ったパターンマッチの find 検索を正式に導入するチケット
  • Ruby 3.0 で入った時はまだ実験的な機能だったので使用すると警告が出てくる
ary = [1, 2, 3]

# warning: Find pattern is experimental, and the behavior may change in future versions of Ruby!
if ary in [*, {a: 0, b: 1 | 2} => i, *]
end
  • Ruby 3.1 で消えるかと思ってたんですけどまだ残ってたみたいですね

[Feature #12962] Feature Proposal: Extend 'protected' to support module friendship

  • protected で宣言した時に後から別のクラスからでも呼び出せるようにする機能の提案
    • C++ にあるような friend 機能
class A
  protected def foo
    "secrets"
  end
end

class D
  def call_foo
    A.new.foo
  end
end

# A のフレンドとして D を登録
A.friend D

# D から A の protected を呼び出すことができるようになる
D.new.call_foo # => "secrets"
  • 他には以下のようにモジュールに対して使用したりとか
module MyLib
  module Internals
  end

  class A
    include Internals
    # Internals を friend することでこれを Internals を include しているクラスから
    # protected なメソッドを呼び出すことができるようになる
    friend Internals

    protected def foo
      "implementation"
    end
  end

  class B
    include Internals
    friend Internals

    protected def bar
      A.new.foo
    end
  end
end

class UserCode
  # include MyLib::Internals してないので protected なメソッドは呼べない
  def call_things
    [MyLib::A.new.foo, MyLib::B.new.bar]
  end
end

class FriendlyUserCode
  # include MyLib::Internals しているので protected なメソッドは呼べる
  include MyLib::Internals

  def call_things
    [MyLib::A.new.foo, MyLib::B.new.bar]
  end
end

UserCode.new.call_things # !> NoMethodError: protected method `foo'..
FriendlyUserCode.new.call_things # => ["implementation", "implementation"]
  • モチベーションとしては機能としてはプライベートな API だけど他の API でも使いたい事があるので Ruby 的な意味での private ではなくて public になっている事がある
    • private にて send で呼び出すこともできるが煩わしい
  • このように機能としてはプライベートだが Ruby として public になっているとユーザが混乱するので明示的に protectedfriend する仕組みがほしいらしい
  • Rubyアクセシビリティを制御するのってむずかしいので friend でちゃんと意識して書くようになるのかはちょっと気になる
  • 個人的には Refinements でメソッドを定義しておいて必要な時に using すればいいんじゃないかと思っている
class A
  # プライベートな API は Refinements で定義しておく
  module Internals
    refine A do
      def foo
        "secrets"
      end
    end
  end
end

class D
  # 使用する箇所で明示的に using する
  using A::Internals

  def call_foo
    A.new.foo
  end
end

D.new.call_foo # => "secrets"