[#113435] [Ruby master Feature#19634] Pattern matching dynamic key — "baweaver (Brandon Weaver) via ruby-core" <ruby-core@...>
Issue #19634 has been reported by baweaver (Brandon Weaver).
6 messages
2023/05/09
[#113489] [Ruby master Bug#19642] Remove vectored read/write from `io.c`. — "ioquatix (Samuel Williams) via ruby-core" <ruby-core@...>
Issue #19642 has been reported by ioquatix (Samuel Williams).
10 messages
2023/05/15
[ruby-core:113478] [Ruby master Feature#19633] Allow passing block to `Kernel#autoload` as alternative to second `filename` argument
From:
"fxn (Xavier Noria) via ruby-core" <ruby-core@...>
Date:
2023-05-14 10:26:49 UTC
List:
ruby-core #113478
Issue #19633 has been updated by fxn (Xavier Noria).
The question was: If `/foo` is a root directory, and you want to associate to it an anonymous module as custom namespace, how would `/foo/bar.rb` look like? So, `/foo/bar.rb` is not `Foo::Bar`. We can also assume, your project has more than one file.
OK, the answer in Zeitwerk is that you need the namespace to be globally available: for example
```ruby
$__MY_GEM = Module.new
loader.push_dir('/foo', namespace: $__MY_GEM)
```
and then you cannot:
```ruby
module $__MY_GEM
class Bar
end
end
```
you necessarily need to use this style:
```ruby
class $__MY_GEM::Bar
end
```
* I have never seen this used
* Inside that body, you cannot refer to other constants in the project using a constant reference as usual, because `$__MY_GEM` is not in the nesting. You have to use constant paths.
* This does not solve isolation, because `$__MY_GEM` is as reachable as `MyGem` is.
This is why Zeitwerk does not support anonymous namespaces today. It would involve work and more complixity in the code base, and probably for nothing.
Wanted to close this circle about the reason anonymous namespaces are not supported today in Zeitwerk.
I'll reflect about the rest of your comments!
----------------------------------------
Feature #19633: Allow passing block to `Kernel#autoload` as alternative to second `filename` argument
https://bugs.ruby-lang.org/issues/19633#change-103061
* Author: shioyama (Chris Salzberg)
* Status: Open
* Priority: Normal
----------------------------------------
`Kernel#autoload` takes two arguments, a symbol `module` representing the constant to be autoloaded, and a `filepath` to load the constant from (with `require`).
Currently, Zeitwerk has to [monkeypatch `Kernel#require`](https://github.com/fxn/zeitwerk/blob/a7c4a983df0f4e4058f32c610dac1e8b99f687da/lib/zeitwerk/kernel.rb) to fetch the loader for the file being loaded, then run the original (aliased) `require`, then run autoload callbacks. In addition to the monkeypatch, this also requires a registry (`Zeitwerk::Registry`) to map file paths to loaders, to know which loader should be used for a given autoload-triggered `require`. In fact, Zeitwerk has to _assume_ that the monkey-patched `require` call came from an autoload trigger; there is no way to really be sure of the source.
If Ruby allowed passing a block as an alternative to the explicit filepath, then I think this could be improved and would eliminate the need for a monkeypatch. So something like this:
```ruby
autoload(:B) do
require "lib/b"
# trigger callback, etc
end
```
I am implementing a gem called [Im](https://github.com/shioyama/im) which is a fork of Zeitwerk, and in the case of this gem, such a feature would be even more useful. Im implements autoloads on anonymous modules by registering an autoload and then "catching" the require and converting it into a `load`, passing the module as the second argument (see [here](https://github.com/shioyama/im/blob/44ce348639a1aae563a5be7a40602761e9698d43/lib/im/kernel.rb).) This is currently quite tricky because, again, it's hard to know _where_ a `require` came from.
In addition to removing the monkeypatch (inherited from Zeitwerk), Im would further benefit from the block argument because then it could simply access the module via a closure, rather than pulling it from a registry:
```ruby
mod.autoload(:Foo) do
load "lib/foo.rb", mod
end
```
I don't know how hard or easy this would be to implement, but if there is interest in this as a feature I'd be happy to look into implementing it.
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- [email protected]
To unsubscribe send an email to [email protected]
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/