2021/06/10 今週の気になった bugs.ruby のチケット
今週は TypeScript のようなコンストラクタを Ruby に導入したい、というチケットなどがありました。
[Feature #17942] Add a initialize(public @a, private @b)
shortcut syntax for defining public/private accessors for instance vars as part of constructor
- TypeScript だと以下のようにコンストラクタのショートハンドを記述できる
class Foo { constructor(public a:number, public b:number, private c:number) { } }
- 上記は以下と同じ意味
class Foo { constructor(a, b, c) { this.a = a; this.b = b; this.c = c; } }
class Thing def initialize(public @a, public @b, @c) end end
- 上記は以下と同じ意味
class Thing attr_accessor :a, :b def initialize(a, b, c) @a = a @b = b @c = c end end
- 個人的には強く
#initialize
に依存してしまっている機能なのでちょっとイマイチ#initialize
はただのコールバックメソッドに過ぎない- メソッドでしかないので他のメソッドでも使えないと一貫性がない
- 仮引数はどうやって参照するの?
- アクセッサまで定義されてるのは意味が強すぎる
- Ruby ではあとから
#initialize
も再定義できるのでその場合にどうなるのかが気になる
class Thing def initialize(public @a, public @b, @c) end end class Thing # こう再定義したらどうなるの? def initialize(@a, public @a) end end
- どうせやるなら宣言的にやったほうがいい気はする
- が、これやるなら gem でいいじゃんって思う
class Thing initialize(public: [:a, :b], private: :c) do end end
- あと
Struct
を使えばアクセシビリティは制御できないがもっと簡素にかける
class Thing < Struct.new(:a, :b, :c) end
- この手の話は定期的に出ている
[Feature #17938] Keyword alternative for boolean positional arguments
bool
値を渡している位置引数をキーワード引数に置き換えようという提案- 例えば以下のメソッドは
true / false
で挙動を制御できるがそれが何を意味しているのかがわからない
object.respond_to?(:symbol, false) # what does `false` mean? object.methods(true) # what does `true` mean?
- なので以下のようにキーワード引数にしようという提案
object.respond_to?(:symbol, include_all: false) object.methods(regular: true) # or object.methods(only_public: true) # or object.methods(include_all: false)
- 実装案は以下のように非互換にならないようするイメージ
def respond_to?(symbol, include_all_positional=false, include_all: nil) include_all ||= include_all_positional # ... end
- 引数を自明にしたいなら以下のように変数に代入すればいいのでは?とコメントされてる
- 流石に変数を定義する副作用がでかい…
- https://bugs.ruby-lang.org/issues/17938#note-4
obj = Object.new obj.respond_to?(:symbol, include_all = false) # or obj.methods(include_inherited = true)
- これは Ruby の問題じゃなくてエディタ側でカバーすべきでは?みたいなコメントもある
- RubyMine とかは仮引数まで含めて補完ができるっぽい
- https://bugs.ruby-lang.org/issues/17938#note-5
- キーワード引数にした場合のキーの名前をどうするのかとパフォーマンスの懸念点が上げられている
[Bug #17925] Pattern matching syntax using semicolon one-line
case expression in 42; end
とワンラインでパターンマッチを記述した場合にエラーになるのは意図する挙動なのか?というバグチケットcase expression when 42; end
みたいにwhen
だおt問題ないcase expression; in 42; end
みたいに;
で区切ると問題ない- これは
case (expression in 42); end
と解釈されてしまっているのが問題らしい
[Bug #17937] Segmentation fault in Enumerator#next on Apple M1, Mac OS Big Sur 11.2.2
- Ruby 2.7.1 + Apple M1, Mac OS Big Sur 11.2.2 で
[1,2,3].to_enum.next
を実行すると Segv するというバグ報告- どうして…
- Ruby 2.7.2 以降と 3.0.1 以降では直っている
[Feature #17930] Add column information into error backtrace
- 先週からの続き
- 現在は
Thread::Backtrace::Location
ではなくてRubyVM::AbstractSyntaxTree.of
で情報を取得する実装が進んでいる
def target # caller_locations[0] は自身のメソッドの呼び出し元の情報を保持している RubyVM::AbstractSyntaxTree.of(caller_locations[0]) end p target #=> #<RubyVM::AbstractSyntaxTree::Node:VCALL@5:2-5:8> # ^^^^^^ Line 5, Column 2--8