From: "shioyama (Chris Salzberg) via ruby-core" Date: 2023-05-17T08:04:50+00:00 Subject: [ruby-core:113502] [Ruby master Feature#19633] Allow passing block to `Kernel#autoload` as alternative to second `filename` argument Issue #19633 has been updated by shioyama (Chris Salzberg). Thanks, that makes sense. In one way we're not far apart. In another, though, I think we still are, because the difference is really between whether control is delegated to the caller or the callee. "isolation", which is what I'm after here, says it should be the caller, not the callee. Allowing the callee to control is not _wrong_ to me, but it's prioritizing the goal that "by looking at your source code, you know the nesting" as you describe. Of course isolation is never complete because _it's Ruby_, and the callee can of course declare `module ::Foo` and escape isolation. I've given up on any kind of _real_ isolation because of concerns expressed by folks like yourself and others, which convinced me Ruby would not make this easy or simple. That said, there are advantages to even partial isolation. I don't want a stray `module Foo` to mean that the caller now has top-level pollution that they did not expect. We're after different goals here, I think both are valid, but they don't really align. That's my conclusion here. And if they do not entirely align, then I will continue maintaining the fork for the foreseeable future. One thing that would make my life easier would be if some of the "utility logic" in Zeitwerk could be extracted into a separate gem. Particularly the loader helpers for crawling directories, etc. Then Im could use that gem without the rest of Zeitwerk. But I can imagine that would be more work for you, and I'm sure you already have enough maintaining such a popular gem, so I don't expect you to do that. :) Just to mention in case it ever is something you consider. ---------------------------------------- Feature #19633: Allow passing block to `Kernel#autoload` as alternative to second `filename` argument https://bugs.ruby-lang.org/issues/19633#change-103097 * 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 -- 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/postorius/lists/ruby-core.ml.ruby-lang.org/