Ruby の Warning[:experimental] = false は実行時に反映されないケースがある
某所でそういう話が出ていたのでいろいろと調べてまとめてみました。
Warning[:deprecated] = true / false
で実行時に非推奨な警告を制御できる
Warning[:deprecated]
に true / false
を割り当てることで実行時に非推奨な警告の出力を制御することができます。
例えば Dir.exists?
は Ruby 3.0 以降では非推奨なので Warning[:deprecated]
が真だと警告文が出力されます。
ちなみに Ruby 2.7 系で試す場合は Enumerator.new([], :each)
など使うと警告が出ます。
# Ruby 2.7.2 以降だとデフォルトでは false pp Warning[:deprecated] # => false # no wanirng Dir.exists?("") # これに true を設定するとそれ以降に呼ばれたメソッドなどで警告が出るようになる Warning[:deprecated] = true # warning: Dir.exists? is deprecated; use Dir.exist? instead Dir.exists?("")
こんな感じで実行時に警告文の出力を制御することができます。
Warning[:experimental] = true / false
の場合は?
Ruby 3.0 ではいくつかの機能が実験的に導入されています。
例えば Ractor
は Ruby 3.0 時点ではまだ実験的な機能になります。
さて、このような実験的な機能を使用すると警告文が出力されることがあります。
# warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. Ractor.new {}
この警告文の出力ですが Warning[:experimental]
を用いることで『実験的な機能に対する』警告文の出力を制御することができます。
# デフォルトでは true pp Warning[:experimental] # => true # 警告が出る # warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. Ractor.new {} # 警告の出力を無効にする Warning[:experimental] = false # 警告が出ない # no warning Ractor.new {}
このように Warning[:experimental] = false
にする事で警告文が出力されなくなります。
Warning[:experimental] = false
で制御できないケースもある
Ruby 3.0 ではパターンマッチの in
を 1行でかける構文も実装されました。
これも Ractor
同様にまだ実験的な機能なので使用すると警告文が出ます。
user = { name: "homu", age: 14 } # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! if user in { age: 1..20 } # ... end
ではこの警告文を Warning[:experimental]
で制御することができるのでしょうか?結論から言うとできませんでした。
user = { name: "homu", age: 14 } # 実験的な警告を無効にする Warning[:experimental] = false # 実験的な警告を無効にしているのに警告が出てしまう # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! if user in { age: 1..20 } # ... end
これはなぜかというと in
を使ったときの警告文の出力が『コンパイル時』に制御されているためです。
なので次のように Ractor.new
が実行時に呼ばれないと警告文を出さないのに対して、 in
の場合は実行時に呼ばれていなくても警告文がでます。
def foo # これは実行時に foo メソッドが呼ばれていないので警告はでない Ractor.new end def hoge # これは実行時に hoge メソッドが呼ばれていなくても警告が出る 42 in n end
一方で Warning[:experimental] = false
というコードは『実行時』に制御を行っているため、コンパイル時には反映されません。
なので例えば eval
などを使って実行時に Ruby のコードを実行する場合は Warning[:experimental]
の設定が反映されます。
user = { name: "homu", age: 14 } Warning[:experimental] = true # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! eval <<~EOS if user in { age: 1..20 } # ... end EOS Warning[:experimental] = false # no warning eval <<~EOS if user in { age: 1..20 } # ... end EOS
このように Warning[:experimental]
で警告文の出力を制御する場合は反映される機能とそうでない機能があるので注意する必要があります。
実験的な機能の警告を無効にするには?
Ruby のコマンドオプションに -W:no-experimental
を付けることで警告文を無効にすることができます。
$ cat main.rb user = { name: "homu", age: 14 } if user in { age: 1..20 } # ... end # 警告が出る $ ruby main.rb main.rb:3: warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby # -W:no-experimental を付けると警告がでない $ ruby -W:no-experimental main.rb $
実験的な機能の警告文を無効にしたい場合はコマンドオプションで制御する方がよさそうですね。