ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
@ 2025-01-03 18:44 Dan0042 (Daniel DeLorme) via ruby-core
  2025-01-06  2:17 ` [ruby-core:120492] " nobu (Nobuyoshi Nakada) via ruby-core
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Dan0042 (Daniel DeLorme) via ruby-core @ 2025-01-03 18:44 UTC (permalink / raw)
  To: ruby-core; +Cc: Dan0042 (Daniel DeLorme)

Issue #21000 has been reported by Dan0042 (Daniel DeLorme).

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)

if obj and defined?(XYZ) === obj

if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120492] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
@ 2025-01-06  2:17 ` nobu (Nobuyoshi Nakada) via ruby-core
  2025-01-06  9:40 ` [ruby-core:120496] " Eregon (Benoit Daloze) via ruby-core
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: nobu (Nobuyoshi Nakada) via ruby-core @ 2025-01-06  2:17 UTC (permalink / raw)
  To: ruby-core; +Cc: nobu (Nobuyoshi Nakada)

Issue #21000 has been updated by nobu (Nobuyoshi Nakada).


Dan0042 (Daniel DeLorme) wrote:
> ### defined?(mod) returns mod if it's a class/module
> 
> If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 
> 
> ```ruby
> case obj
> when nil
> when defined?(XYZ)
> 
> if obj and defined?(XYZ) === obj
> 
> if defined?(Gem::Specification)&.respond_to?(:each)
> ```
> Very versatile, with the downside that it's a small backward incompatibiliy.

I like this, but we will need to consider the incompatibility and inconsistency with other constants.


----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111277

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)

if obj and defined?(XYZ) === obj

if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120496] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
  2025-01-06  2:17 ` [ruby-core:120492] " nobu (Nobuyoshi Nakada) via ruby-core
@ 2025-01-06  9:40 ` Eregon (Benoit Daloze) via ruby-core
  2025-01-06 13:32 ` [ruby-core:120501] " Dan0042 (Daniel DeLorme) via ruby-core
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2025-01-06  9:40 UTC (permalink / raw)
  To: ruby-core; +Cc: Eregon (Benoit Daloze)

Issue #21000 has been updated by Eregon (Benoit Daloze).


`defined?` so far always returned `nil` or frozen strings, so I think it's not so great to use for this.

Also `defined?` is particularly error-prone for constants & autoloading, for instance:
```
$DEBUG = true # to show swallowed exceptions

autoload :Foo, "foo"

p defined?(Foo) # nil

p defined?(Foo::Bar)
# Exception 'LoadError' at /home/eregon/.rubies/ruby-3.4.1/lib/ruby/3.4.0/rubygems.rb:1369 - cannot load such file -- rubygems/defaults/operating_system
# Exception 'LoadError' at /home/eregon/.rubies/ruby-3.4.1/lib/ruby/3.4.0/rubygems.rb:1386 - cannot load such file -- rubygems/defaults/ruby
# Exception 'LoadError' at <internal:/home/eregon/.rubies/ruby-3.4.1/lib/ruby/3.4.0/rubygems/core_ext/kernel_require.rb>:136 - cannot load such file -- foo
# Exception 'LoadError' at <internal:/home/eregon/.rubies/ruby-3.4.1/lib/ruby/3.4.0/rubygems/core_ext/kernel_require.rb>:144 - cannot load such file -- foo
nil
```
So `defined?(Foo::Bar)` will actually try to load `Foo`.

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111283

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)

if obj and defined?(XYZ) === obj

if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120501] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
  2025-01-06  2:17 ` [ruby-core:120492] " nobu (Nobuyoshi Nakada) via ruby-core
  2025-01-06  9:40 ` [ruby-core:120496] " Eregon (Benoit Daloze) via ruby-core
@ 2025-01-06 13:32 ` Dan0042 (Daniel DeLorme) via ruby-core
  2025-01-06 14:26 ` [ruby-core:120502] " Eregon (Benoit Daloze) via ruby-core
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Dan0042 (Daniel DeLorme) via ruby-core @ 2025-01-06 13:32 UTC (permalink / raw)
  To: ruby-core; +Cc: Dan0042 (Daniel DeLorme)

Issue #21000 has been updated by Dan0042 (Daniel DeLorme).


Eregon (Benoit Daloze) wrote in #note-2:
> So `defined?(Foo::Bar)` will actually try to load `Foo`.

It would be a good idea to fix that right?

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111294

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)

if obj and defined?(XYZ) === obj

if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120502] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (2 preceding siblings ...)
  2025-01-06 13:32 ` [ruby-core:120501] " Dan0042 (Daniel DeLorme) via ruby-core
@ 2025-01-06 14:26 ` Eregon (Benoit Daloze) via ruby-core
  2025-01-06 14:32 ` [ruby-core:120503] " Dan0042 (Daniel DeLorme) via ruby-core
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2025-01-06 14:26 UTC (permalink / raw)
  To: ruby-core; +Cc: Eregon (Benoit Daloze)

Issue #21000 has been updated by Eregon (Benoit Daloze).


I'm unsure, I suppose it could be a compatibility concern.
If you want to know if `Foo::Bar` exists and `Foo` is an autoload the only way to know is to load Foo and see if it has a constant `Bar`.
So while surprising these semantics do make sense since `defined?` doesn't have a "it's an autoload (not yet loaded), I don't know" return value, it's either `nil` (doesn't exist) or `"constant"` (exists).

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111295

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)

if obj and defined?(XYZ) === obj

if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120503] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (3 preceding siblings ...)
  2025-01-06 14:26 ` [ruby-core:120502] " Eregon (Benoit Daloze) via ruby-core
@ 2025-01-06 14:32 ` Dan0042 (Daniel DeLorme) via ruby-core
  2025-01-07 10:18 ` [ruby-core:120519] " mame (Yusuke Endoh) via ruby-core
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Dan0042 (Daniel DeLorme) via ruby-core @ 2025-01-06 14:32 UTC (permalink / raw)
  To: ruby-core; +Cc: Dan0042 (Daniel DeLorme)

Issue #21000 has been updated by Dan0042 (Daniel DeLorme).


While these semantics make a certain sense, the opposite also makes just as much sense. If `Foo` is not yet autoloaded, that means neither `Foo` nor `Foo::Bar` are yet defined, and it makes sense to return falsy for both. At the very least `defined?(Foo)` and `defined?(Foo::Bar)` should be consistent.

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111296

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)

if obj and defined?(XYZ) === obj

if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120519] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (4 preceding siblings ...)
  2025-01-06 14:32 ` [ruby-core:120503] " Dan0042 (Daniel DeLorme) via ruby-core
@ 2025-01-07 10:18 ` mame (Yusuke Endoh) via ruby-core
  2025-01-07 15:56 ` [ruby-core:120527] " Dan0042 (Daniel DeLorme) via ruby-core
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: mame (Yusuke Endoh) via ruby-core @ 2025-01-07 10:18 UTC (permalink / raw)
  To: ruby-core; +Cc: mame (Yusuke Endoh)

Issue #21000 has been updated by mame (Yusuke Endoh).


When you create a ticket, please state clearly the problem you wish to solve.

Here is my understanding. You see *two* problems with the following idiom

```ruby
if defined?(Foo) and obj.is_a?(Foo)
```

* This idiom fires autoload. Before the actual load, there is no way that `obj` could be an instance of Foo, so we can tell "false" without firing autoload.
* It is redundant to write the constant name twice.

Therefore, you want a way to write a decision similar to this idiom without firing autoload. Preferably without writing the constant name twice.

Is my understanding right?

If so, how would your last proposal that `defined?(XYZ)` return `XYZ` solve this problem?
Currently, for the constant `XYZ` for which autoload is set, `defined?(XYZ)` returns `"constant"` even before the actual load.
If it were to return `XYZ` itself, I don't think it would solve the autoload problem.
Or does your proposal involve changing `defined?(XYZ)` to return `nil` if it is before the actual load? I don't think that is a small incompatibility.

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111324

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)
```
```ruby
if obj and defined?(XYZ) === obj
```
```ruby
if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120527] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (5 preceding siblings ...)
  2025-01-07 10:18 ` [ruby-core:120519] " mame (Yusuke Endoh) via ruby-core
@ 2025-01-07 15:56 ` Dan0042 (Daniel DeLorme) via ruby-core
  2025-01-07 16:25 ` [ruby-core:120528] " Eregon (Benoit Daloze) via ruby-core
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Dan0042 (Daniel DeLorme) via ruby-core @ 2025-01-07 15:56 UTC (permalink / raw)
  To: ruby-core; +Cc: Dan0042 (Daniel DeLorme)

Issue #21000 has been updated by Dan0042 (Daniel DeLorme).


mame (Yusuke Endoh) wrote in #note-7:
> When you create a ticket, please state clearly the problem you wish to solve.

The problem I wish to solve is the repetition of `NameSpace::ClassName` in the idiom mentioned above.

Apologies if this wasn't clear enough in the original description—I may not have formatted it effectively.

In the third idea I mentioned autoload as a possible solution in the context of pattern matching, but I hadn't really considered autoload in the context of `defined?(XYZ)` in the fourth idea.

To clarify, my fourth idea was:
```ruby
defined?(NothingHere) #=> nil
N = nil
defined?(N) #=> "constant"
XYZ = Class.new
defined?(XYZ) #=> XYZ
```

I hadn’t accounted for how `defined?` should behave with an autoloaded constant. @eregon mentioned `p defined?(Foo) # nil` but it actually returns "constant", which I wasn't aware of. 

I think it would make sense for `defined?(Foo)` to return `nil` for a not-yet-loaded autoload constant. Alternatively, it could trigger autoload and return `Foo` if it resolves to a module. But as you said that is no longer a small incompatibility.


----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111331

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)
```
```ruby
if obj and defined?(XYZ) === obj
```
```ruby
if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120528] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (6 preceding siblings ...)
  2025-01-07 15:56 ` [ruby-core:120527] " Dan0042 (Daniel DeLorme) via ruby-core
@ 2025-01-07 16:25 ` Eregon (Benoit Daloze) via ruby-core
  2025-01-07 18:43 ` [ruby-core:120532] " Dan0042 (Daniel DeLorme) via ruby-core
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2025-01-07 16:25 UTC (permalink / raw)
  To: ruby-core; +Cc: Eregon (Benoit Daloze)

Issue #21000 has been updated by Eregon (Benoit Daloze).


Dan0042 (Daniel DeLorme) wrote in #note-8:
> I hadn’t accounted for how `defined?` should behave with an autoloaded constant. [@Eregon (Benoit Daloze)](/users/772) mentioned `p defined?(Foo) # nil` but it actually returns "constant", which I wasn't aware of.

Sorry about that, it is indeed `constant`, I must have made a copy-paste mistake.
Here is the full code and output:
```
$ ruby -de 'autoload :Foo, "foo"; p defined?(Foo); p defined?(Foo::Bar)'
Exception `LoadError' at /home/eregon/.rubies/ruby-3.3.5/lib/ruby/3.3.0/rubygems.rb:1346 - cannot load such file -- rubygems/defaults/operating_system
Exception `LoadError' at /home/eregon/.rubies/ruby-3.3.5/lib/ruby/3.3.0/rubygems.rb:1363 - cannot load such file -- rubygems/defaults/ruby
"constant"
Exception `LoadError' at <internal:/home/eregon/.rubies/ruby-3.3.5/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136 - cannot load such file -- foo
Exception `LoadError' at <internal:/home/eregon/.rubies/ruby-3.3.5/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:144 - cannot load such file -- foo
nil
```

So indeed `defined?(Foo)` returns `"constant"` without trying to load it, and `defined?(Foo::Bar)` triggers the autoload.

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111332

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)
```
```ruby
if obj and defined?(XYZ) === obj
```
```ruby
if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120532] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (7 preceding siblings ...)
  2025-01-07 16:25 ` [ruby-core:120528] " Eregon (Benoit Daloze) via ruby-core
@ 2025-01-07 18:43 ` Dan0042 (Daniel DeLorme) via ruby-core
  2025-01-08  1:46 ` [ruby-core:120544] " mame (Yusuke Endoh) via ruby-core
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Dan0042 (Daniel DeLorme) via ruby-core @ 2025-01-07 18:43 UTC (permalink / raw)
  To: ruby-core; +Cc: Dan0042 (Daniel DeLorme)

Issue #21000 has been updated by Dan0042 (Daniel DeLorme).


After some further thought, I believe the fourth idea could work if autoload constants simply returned "constant". Because if a constant isn’t yet autoloaded, no objects of that type can exist. To recap:

```ruby
defined?(NothingHere) #=> nil

N = nil
defined?(N) #=> "constant"

XYZ = Class.new
defined?(XYZ) #=> XYZ

autoload :Foo, "foo"
defined?(Foo) #=> "constant"
```

With this approach, we’re back to only a small incompatibility. I describe it as "small" because `defined?` is almost always used as a boolean condition. I've only found 1 gem that uses the return value of `defined?` beyond checking its truthiness, and even then, it's for "method", not "constant"

	oj-3.13.14/test/helper.rb
	22:if defined?(GC.verify_compaction_references) == 'method'

	oj-3.13.14/test/json_gem/test_helper.rb
	18:  if defined?(GC.verify_compaction_references) == 'method'


----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111334

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)
```
```ruby
if obj and defined?(XYZ) === obj
```
```ruby
if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120544] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (8 preceding siblings ...)
  2025-01-07 18:43 ` [ruby-core:120532] " Dan0042 (Daniel DeLorme) via ruby-core
@ 2025-01-08  1:46 ` mame (Yusuke Endoh) via ruby-core
  2025-01-08  9:55 ` [ruby-core:120554] " Eregon (Benoit Daloze) via ruby-core
  2025-01-08 14:36 ` [ruby-core:120558] " Dan0042 (Daniel DeLorme) via ruby-core
  11 siblings, 0 replies; 13+ messages in thread
From: mame (Yusuke Endoh) via ruby-core @ 2025-01-08  1:46 UTC (permalink / raw)
  To: ruby-core; +Cc: mame (Yusuke Endoh)

Issue #21000 has been updated by mame (Yusuke Endoh).


If you just want to avoid repetition and don't care autoload, I found a good (and magical) way to do it.

```ruby
class TrueClass
  def true?
  end
end

if defined?(obj.is_a?(NameSpace::ClassName).true?)
  # obj is a NameSpace::ClassName
else
  # obj is not a NameSpace::ClassName
end

# or, more magically

if defined?(-(obj.is_a?(NameSpace::ClassName)&&1))
  # obj is a NameSpace::ClassName
else
  # obj is not a NameSpace::ClassName
end
```

The behavior of `defined?` that actually evaluates the some part is sometimes convenient :-)

I don't think my idiom is nice, though. It is too magical. And, I think `if obj and defined?(XYZ) === obj` is too magical as well.

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111348

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)
```
```ruby
if obj and defined?(XYZ) === obj
```
```ruby
if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120554] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (9 preceding siblings ...)
  2025-01-08  1:46 ` [ruby-core:120544] " mame (Yusuke Endoh) via ruby-core
@ 2025-01-08  9:55 ` Eregon (Benoit Daloze) via ruby-core
  2025-01-08 14:36 ` [ruby-core:120558] " Dan0042 (Daniel DeLorme) via ruby-core
  11 siblings, 0 replies; 13+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2025-01-08  9:55 UTC (permalink / raw)
  To: ruby-core; +Cc: Eregon (Benoit Daloze)

Issue #21000 has been updated by Eregon (Benoit Daloze).


IMO the pattern is not frequent enough to justify adding new syntax for this or breaking compatibility.
In https://pastebin.com/VGfjRWNu many cases are actually not classes, e.g. `defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED`, `defined?(RUBY_ENGINE) and RUBY_ENGINE == 'jruby'`, etc.

Maybe a new method or kwarg to `const_get` which has some special behavior regarding autoload (to not trigger them)?

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111365

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)
```
```ruby
if obj and defined?(XYZ) === obj
```
```ruby
if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:120558] [Ruby master Feature#21000] A way to avoid loading constant required by a type check
  2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
                   ` (10 preceding siblings ...)
  2025-01-08  9:55 ` [ruby-core:120554] " Eregon (Benoit Daloze) via ruby-core
@ 2025-01-08 14:36 ` Dan0042 (Daniel DeLorme) via ruby-core
  11 siblings, 0 replies; 13+ messages in thread
From: Dan0042 (Daniel DeLorme) via ruby-core @ 2025-01-08 14:36 UTC (permalink / raw)
  To: ruby-core; +Cc: Dan0042 (Daniel DeLorme)

Issue #21000 has been updated by Dan0042 (Daniel DeLorme).


Eregon (Benoit Daloze) wrote in #note-12:
> Maybe a new method or kwarg to `const_get` which has some special behavior regarding autoload (to not trigger them)?

That sounds good to me. What about `Object.const_dig(:JSON, :JSON_LOADED)` which returns nil if at any point the constant is not defined or not yet autoloaded.

It can even mirror the #dig behavior:
```ruby
Object.const_dig(:JSON, :JSON_LOADED, :SOMETHING)
# TrueClass does not have #const_dig method (TypeError)
```

----------------------------------------
Feature #21000: A way to avoid loading constant required by a type check
https://bugs.ruby-lang.org/issues/21000#change-111368

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
There is this pattern I encounter sometimes:

```ruby
if defined?(NameSpace::ClassName) and obj.is_a?(NameSpace::ClassName)
```

Searching in gems, the pattern is fairly common: https://pastebin.com/VGfjRWNu

I would like a way to avoid the repetition of `NameSpace::ClassName` above.  I can think of a number of ways to approach the issue, each with different tradeoffs...


### Pattern match ignores uninitialized constant 

Pattern match like `obj in XYZ` could return false if XYZ is not defined. The danger here is that a typo could go undetected and just silently ignore the error even when the constants is expected to be defined.

### Pattern match has special syntax to ignore uninitialized constant 

Pattern match such as `obj in XYZ?` (or some other syntax) could return false if XYZ is not defined. The downside is that we're adding yet more new syntax. But it could be `obj in defined?(XYZ)` and then it doesn't really feel like new syntax.

### Do not autoload constants required by pattern match

If we have `autoload :XYZ, "xyz"` then `obj in XYZ` could skip the autoload and return false. There is a possibility that `XYZ` might be defined as a regexp or other matcher that return true, but in general autoload is only used for classes/modules. And if the class/module is not yet loaded, obviously an object of that type cannot exist so we can avoid loading it. But this would only work for autoloaded constants, so can't be used to check a library that might not be loaded, ex: `obj in ActiveRecord::Base`

### defined?(mod) returns mod if it's a class/module

If XYZ is a module, `defined?(XYZ)` could return XYZ instead of returning "constant". So it can be used in expressions like 

```ruby
case obj
when nil
when defined?(XYZ)
```
```ruby
if obj and defined?(XYZ) === obj
```
```ruby
if defined?(Gem::Specification)&.respond_to?(:each)
```
Very versatile, with the downside that it's a small backward incompatibiliy.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2025-01-08 14:37 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-03 18:44 [ruby-core:120469] [Ruby master Feature#21000] A way to avoid loading constant required by a type check Dan0042 (Daniel DeLorme) via ruby-core
2025-01-06  2:17 ` [ruby-core:120492] " nobu (Nobuyoshi Nakada) via ruby-core
2025-01-06  9:40 ` [ruby-core:120496] " Eregon (Benoit Daloze) via ruby-core
2025-01-06 13:32 ` [ruby-core:120501] " Dan0042 (Daniel DeLorme) via ruby-core
2025-01-06 14:26 ` [ruby-core:120502] " Eregon (Benoit Daloze) via ruby-core
2025-01-06 14:32 ` [ruby-core:120503] " Dan0042 (Daniel DeLorme) via ruby-core
2025-01-07 10:18 ` [ruby-core:120519] " mame (Yusuke Endoh) via ruby-core
2025-01-07 15:56 ` [ruby-core:120527] " Dan0042 (Daniel DeLorme) via ruby-core
2025-01-07 16:25 ` [ruby-core:120528] " Eregon (Benoit Daloze) via ruby-core
2025-01-07 18:43 ` [ruby-core:120532] " Dan0042 (Daniel DeLorme) via ruby-core
2025-01-08  1:46 ` [ruby-core:120544] " mame (Yusuke Endoh) via ruby-core
2025-01-08  9:55 ` [ruby-core:120554] " Eregon (Benoit Daloze) via ruby-core
2025-01-08 14:36 ` [ruby-core:120558] " Dan0042 (Daniel DeLorme) via ruby-core

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).