From: manga.osyo@... Date: 2018-12-30T08:18:17+00:00 Subject: [ruby-dev:50740] [Ruby trunk Bug#15488] const_defined?("File::NULL") の挙動 Issue #15488 has been updated by osyo (manga osyo). 挙動を修正したパッチを書いてみました。 ただ、意図的にそのような実装にしていた節があるのでこれが仕様なのかバグなのかは現時点で判断するのはちょっとむずかしそうですね。 該当箇所を消してもテストはパスしていたんですが…。 わたしも処理に一貫性を持たせるためには `true` を返したほうがいいと思います。 * pull requst : https://github.com/ruby/ruby/pull/2061 また、元々は以下の issues で議論されていたようです。 * [Feature #7414: Now that const_get supports `Foo::Bar`; syntax, so should const_defined?. - Ruby trunk - Ruby Issue Tracking System](https://bugs.ruby-lang.org/issues/7414) ## 挙動 ### 修正前 ```ruby module M HOGE = 42 end class X include M end # OK: 問題なく取得できる p X.const_get("HOGE") # => 42 p Object.const_get("X::HOGE") # => 42 # OK: 期待する値が返ってくる p X.const_defined?("HOGE") # => true # NG: const_get で値は取得できるが false が返ってくる p Object.const_defined?("X::HOGE") # => false ``` ### 修正後 ```ruby module M HOGE = 42 end class X include M end # OK: 問題なく取得できる p X.const_get("HOGE") # => 42 p Object.const_get("X::HOGE") # => 42 # OK: 期待する値が返ってくる p X.const_defined?("HOGE") # => true # OK: true が返ってくる p Object.const_defined?("X::HOGE") # => true # OK: 第二引数に false を渡すと mixin が考慮されないようになるので false になる p Object.const_defined?("X::HOGE", false) # => false ``` ## ユースケース 定数が存在しない場合に動的に mixin を行いたい場合は `include` が考慮されていてほしい。 ```ruby module Valuable VALUE = 42 end class X end def get # 遅延して mixin する if !Object.const_defined?("X::VALUE") pp "homu" X.include Valuable end Object.const_get("X::VALUE") end # 最初のメソッド呼び出しでのみ mixin したい p get p get p get ``` ---------------------------------------- Bug #15488: const_defined?("File::NULL") の挙動 https://bugs.ruby-lang.org/issues/15488#change-76004 * Author: shuujii (Shuji KOBAYASHI) * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux] * Backport: 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: UNKNOWN ---------------------------------------- `const_get` と `const_defined?` について、例えば `Math::PI` では以下のようになり どちらも期待通りの結果になります。 ~~~ruby p Object.const_get("Math::PI") #=> 3.141592653589793 p Object.const_defined?("Math::PI") #=> true ~~~ 一方、`File::NULL` の場合は以下のように `const_get` で値が取得できるのに `const_defined?` が `false` になります。 ~~~ruby p Object.const_get("File::NULL") #=> "/dev/null" p Object.const_defined?("File::NULL") #=> false ~~~ これは意図的でしょうか。 -- https://bugs.ruby-lang.org/