ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: "shioyama (Chris Salzberg)" <noreply@ruby-lang.org>
To: ruby-core@ruby-lang.org
Subject: [ruby-core:110071] [Ruby master Feature#10320] require into module
Date: Sun, 25 Sep 2022 12:54:09 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-99322.20220925125408.7501@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-10320.20141002224417.7501@ruby-lang.org

Issue #10320 has been updated by shioyama (Chris Salzberg).


I think there are some misunderstandings, which are at least partly my fault for not being clearer about my intentions here.

There are two things I presented earlier in this thread:
- changes to Ruby ([here](https://github.com/shioyama/ruby/tree/import_modules)) to make the `load` wrap module transitive in `require`, including native extension code, and some other smaller changes around `name`.
- a gem ([Im](https://github.com/shioyama/im)) which takes advantage of those changes to implement imports

I do not intend to propose here that everything that's in the gem be implemented in Ruby itself. My intention is to motivate changes at the language level necessary to open the door to gems like Im do implement imports in whatever way gem owners see fit.

> It looks like Im attempts to handle the above case by copying global constants into the module. I doubt we would want to do that in `load` or `require`.

Agreed, I had always imagined that this was something that could be done at the gem level, or not at all, depending on needs.

> To me, this example is a perfect indication of why we shouldn't support this. This uses `import` to load `ActiveSupport`, so that `ActiveSupport` is not added to top level namespace, but all of the core extensions added by `ActiveSupport` are still active. The namespace isolation is only partial, it is not complete.

The namespace isolation _as implemented in the gem_ is only partial. The Ruby side should IMO be as close as possible to absolute isolation, so e.g. toplevel references in the wrapped module should resolve to the module top, not absolute top. This way the importer has full control over what constants to make available to the wrapped script.

But this of course poses a problem for basic classes that can be monkeypatched (`String`, `Hash`, etc) I don't know what the solution for that is but it seems to me the problem there is more with monkeypatching as a common practice than it is with imports (potentially) giving access to those classes across multiple imports.

> I'm against `require` accepting a module similar to `load`, and against making the module wrapping behavior transitive, so that `require` and `load` automatically use the currently wrapping module.

To be clear, I'm also against the former. 

The latter (transitivity of the wrap module to `require`) is a dealbreaker though because if we do not have transitivity, then existing code will never be importable without rewriting it. I am not suggesting it has to be `load`, but transitivity _somewhere_ to `require` is going to be necessary in order for any kind of code importing to be practically useful.

The discussion of loading multiple versions of a gem is interesting, but I don't think it's terribly relevant to deciding whether Ruby should support transitivity of wrapping behaviour. What I implemented in the gem, with constant aliases, was one way of dealing with core extensions, and it works (sort of) for loading gems like Rails that monkey-patch core classes. Of course this would cause problems loading multiple versions of a gem, but I'm not suggesting Ruby ever should do this.

----------------------------------------
Feature #10320: require into module
https://bugs.ruby-lang.org/issues/10320#change-99322

* Author: sowieso (So Wieso)
* Status: Open
* Priority: Normal
----------------------------------------
When requiring a library, global namespace always gets polluted, at least with one module name. So when requiring a gem with many dependencies, at least one constant enters global namespace per dependency, which can easily get out of hand (especially when gems are not enclosed in a module).

Would it be possible to extend require (and load, require_relative) to put all content into a custom module and not into global namespace?

Syntax ideas:

~~~ruby
require 'libfile', into: :Lib   # keyword-argument
require 'libfile' in Lib   # with keyword, also defining a module Lib at current binding (unless defined? Lib)
require_qualified 'libfile', :Lib
~~~

This would also make including code into libraries much easier, as it is well scoped.

~~~ruby
module MyGem
  require 'needed' in Need

  def do_something
    Need::important.process!
  end
end
 # library user is never concerned over needed's content
~~~

Some problems to discuss:

* requiring into two different modules means loading the file twice?
* monkeypatching libraries should only affect the module ­→ auto refinements?
* maybe also allow a binding as argument, not only a module?
* privately require, so that required constants and methods are not accessible from the outside of a module (seems to difficult)
* what about $global constants, read them from global scope but copy-write them only to local scope?

Similar issue:
https://bugs.ruby-lang.org/issues/5643



-- 
https://bugs.ruby-lang.org/

  parent reply	other threads:[~2022-09-25 12:54 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-10320.20141002224417.7501@ruby-lang.org>
2021-06-10  5:51 ` [ruby-core:104226] [Ruby master Feature#10320] require into module j.ruby-lang
2021-06-10  6:18 ` [ruby-core:104227] " branzeanu.aurel
2021-06-10  8:15 ` [ruby-core:104228] " j.ruby-lang
2022-09-15  3:19 ` [ruby-core:109898] " shioyama (Chris Salzberg)
2022-09-16  6:52 ` [ruby-core:109915] " Eregon (Benoit Daloze)
2022-09-16  7:34 ` [ruby-core:109916] " shyouhei (Shyouhei Urabe)
2022-09-16 10:52 ` [ruby-core:109918] " nobu (Nobuyoshi Nakada)
2022-09-16 21:45 ` [ruby-core:109923] " byroot (Jean Boussier)
2022-09-17  1:53 ` [ruby-core:109925] " shioyama (Chris Salzberg)
2022-09-17  2:00 ` [ruby-core:109926] " shioyama (Chris Salzberg)
2022-09-17  2:32 ` [ruby-core:109927] " shioyama (Chris Salzberg)
2022-09-18 10:43 ` [ruby-core:109946] " shyouhei (Shyouhei Urabe)
2022-09-19  8:25 ` [ruby-core:109955] " duerst
2022-09-19  8:32 ` [ruby-core:109956] " byroot (Jean Boussier)
2022-09-19 17:23 ` [ruby-core:109959] " vo.x (Vit Ondruch)
2022-09-20 10:58 ` [ruby-core:109960] " retro
2022-09-21  9:46 ` [ruby-core:109973] " mame (Yusuke Endoh)
2022-09-21 10:26 ` [ruby-core:109974] " byroot (Jean Boussier)
2022-09-21 12:39 ` [ruby-core:109979] " shioyama (Chris Salzberg)
2022-09-21 17:08 ` [ruby-core:109981] " mame (Yusuke Endoh)
2022-09-21 18:11 ` [ruby-core:109982] " jeremyevans0 (Jeremy Evans)
2022-09-25 12:54 ` shioyama (Chris Salzberg) [this message]
2022-09-27  0:54 ` [ruby-core:110098] " shioyama (Chris Salzberg)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-99322.20220925125408.7501@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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 read-only IMAP folder(s) and NNTP newsgroup(s).