2020/09/17 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
[Feature #17171] Why is the visibility of constants not affected by private
?
- 次のように
Module#private
に引数を渡さなかった場合、それ以降に定義されたメソッドはprivate
メソッドになる
class X private # hoge は private メソッドになる def hoge end end
- このときに定数を定義した場合も
private
になるようにする提案
class X private # これも private になってほしい PI = 3.14 # private_const で private 化は可能 # private_const :PI end
- DSL としてみれば定数も
private
になるのは自然な気がする - これを入れると非互換な変更になるのでこわい
[Feature #17104] Do not freeze interpolated strings when using frozen-string-literal
#frozen_string_literal: true
を設定したファイルで文字列の式展開を行うとその文字列はfrozen
になる
#frozen_string_literal: true # これは frozen string str = "hoge" p str.frozen? # => true # これも frozen string str2 = "(#{str + str})" p str2.frozen? # => true
- しかし、式展開の文字列は実行毎に新しい文字列が生成されるので
frozen
にする意味がないのでは?というのがこのチケットの議題
#frozen_string_literal: true # これは同じオブジェクトを共有している str1 = "hoge" str2 = "hoge" p str1.__id__ # => 60 p str2.__id__ # => 60 # これは同じ書き方だがオブジェクトは異なる str3 = "(#{str1})" str4 = "(#{str1})" p str3.__id__ # => 80 p str4.__id__ # => 100
- このチケットにより式展開した文字列は
frozen
にならないようになった
str = "hoge" str2 = "(#{str + str})" p str2.frozen? # 2.7.0 => true # 3.0.0 => false
- この変更はすでにマージ済み
[Feature #16806] Struct#initialize accepts keyword arguments too by default
Struct
で生成したクラスを.new
する時にキーワード引数で初期値を渡したい場合はStruct.new
にkeyword_init: true
にする必要がある
# keyword_init: true にすると User.new にキーワード引数を渡して生成できる User = Struct.new(:name, :age, keyword_init: true) homu = User.new(name: "homu", age: 14)
- これを
keyword_init: true
にしなくてもキーワード引数で生成できるようしようという提案
User = Struct.new(:name, :age) # これは以前の挙動のまま homu = User.new("homu", 14) # キーワード引数を渡すと keyword_init: true と同じように初期化される homu = User.new(name: "homu", age: 14)
- ただし、以下のようなケースで互換性が壊れるかもしれない
User = Struct.new(:name, :age) # 現状だと name に Hash オブジェクトが入ってしまうので既存の挙動と変わってしまう p User.new(name: "homu", age: 14) # => #<struct User name={:name=>"homu", :age=>14}, age=nil>
- 互換性は気になるけど
keyword_init
を使わなくて済むのは便利そう
[Feature #17165] Add filter
and flatten
keywords to Enumerable#map
- 問題の起点としては
filter_map
とflat_map
を同時に使うことができない - この問題を解決する手段として
Enumerable#map
にfilter:
とflatten:
キーワード引数を入れようという提案
array.map(filter: true, flatten: 1) do |foo| bar = baz(foo) next unless bar bar.map{...} end
- 複雑な組み合わせをしないでよくはなるので便利そうではあるけどキーワード引数で制御するのはウーン
merge, fix されたチケット
- [Bug #15412] OpenStruct error when attribute is called 'method'
OpenStruct
で既存のメソッドも上書きできるようになった
- [Feature #17104] Do not freeze interpolated strings when using frozen-string-literal
"#{str}"
みたいな式展開文字列は#frozen_string_literal: true
で frozen にならなくなる