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

あけましておめでとうございます。
今年も引き続き書いていきたいと思います。
今週は Refinement 周りの便利メソッドが追加されたり匿名な * ** 引数をフォワードする機能がマージされました。

[Feature #18460] implicit self for .() syntax without rvalue

  • self を付けないで .() を呼び出せるようにする提案
m = 1.method(:+)
# 1.+(3) を呼びだす
m.(2) # 3

# self.() で呼び出せる
m.instance_exec { self.(2) }

# self なしで .() で呼び出せるようにしたい
m.instance_exec { .(2) }

[Feature #18459] IRB autocomplete dropdown colour options

  • Ruby 3.1 で入った irb の自動補完のダイアログの色をユーザ側で制御したいという提案
IRB.conf[:AUTOCOMPLETE] = {
  BG_COLOR: 0,
  FG_COLOR: 15,
}
  • 最近の irb だと色々とハイライトされるようになっているので細かいハイライトが制御できるようになるとよいんですかね?

[Bug #18294] error when parsing regexp comment

# これは OK
_re = /
  foo  # これはコメント
/x

# コメントにエスケープされた文字があるとエラーになる
_re = /
  foo  # \M-ca
/x
# /tmp/vxUTJfT/17:8: Invalid escape character syntax
#   foo  # \M
#          ^~
/ C:\\[a-z]{5} # e.g. C:\users /x
# =>                      ^
# => invalid Unicode escape (SyntaxError)

[Feature #12737] Module#defined_refinements

  • レシーバで定義されている refine されたオブジェクトとその Refinement オブジェクトの Hash を返す Module#defined_refinements メソッドを追加する提案
module M
  refine String do
    $M_String = self
  end

  refine Integer do
    $M_Integer = self
  end
end

p M.defined_refinements #=> {String => $M_String, Integer => $M_Integer}
  • 最終的にモジュール内で定義されている Refinement オブジェクトを返す Module#refinementsrefine されているクラスを取得する Refinement#refined_class の2つのメソッドが追加された
module Ex
  refine Integer do
    # ...
  end

  refine String do
    # ...
  end
end

pp Ex.refinements
# => [#<refinement:Integer@Ex>, #<refinement:String@Ex>]

# refine されているクラスを返す
pp Ex.refinements.first.refined_class
# => Integer

[Bug #18441] Fix inconsistent parentheses with anonymous block forwarding

  • Ruby ではメソッド定義やメソッド呼び出しの () は省略する事ができる
def demo positional, &block
  other positional, &block
end
  • しかし、次のように Ruby 3.1 で追加された匿名のブロック引数を受け取ったり渡したりするとエラーになる
# syntax error, unexpected local variable or method, expecting ';' or '\n'
# other positional, &
#       ^~~~~~~~~~
def demo positional, &
  other positional, &
end
  • これが一貫性がいないというバグ報告
  • これは Ruby& の後にブロック変数名を探索するので
def a &
  b
  b
end
  • が、次のように解釈される為
def a(&b)
  b
end
  • なので
def demo positional, &
  other positional, &
end
def demo(positional, &other positional, &)
end
  • とパースされるらしい
  • ちなみに ; を付けると () を付けなくても呼び出せる
def demo positional, &;
  other positional, &
end

def demo positional, &;
  other positional, &;
  another positional, &
end
  • このチケットは Reject されている

deprecated な機能が削除されてる

マージされた機能

def foo(*)
  bar(*)

  # こう書くこともできる
  piyo(*, *)
end

def baz(**)
  quux(**)
end