ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope
@ 2021-03-26 19:19 tenderlove
  2021-03-27  7:58 ` [ruby-core:103053] " sawadatsuyoshi
                   ` (29 more replies)
  0 siblings, 30 replies; 31+ messages in thread
From: tenderlove @ 2021-03-26 19:19 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been reported by tenderlovemaking (Aaron Patterson).

----------------------------------------
Feature #17753: Add Module#outer_scope
https://bugs.ruby-lang.org/issues/17753

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)


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

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

* [ruby-core:103053] [Ruby master Feature#17753] Add Module#outer_scope
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
@ 2021-03-27  7:58 ` sawadatsuyoshi
  2021-03-27 11:33 ` [ruby-core:103057] " eregontp
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: sawadatsuyoshi @ 2021-03-27  7:58 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by sawa (Tsuyoshi Sawada).


What would you expect if a constant has multiple names?

```ruby
module E; end
E::F = A::B::C
```

Should `A::B::C.outer_scope` return `A::B` or `E`?


----------------------------------------
Feature #17753: Add Module#outer_scope
https://bugs.ruby-lang.org/issues/17753#change-91114

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)


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

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

* [ruby-core:103057] [Ruby master Feature#17753] Add Module#outer_scope
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
  2021-03-27  7:58 ` [ruby-core:103053] " sawadatsuyoshi
@ 2021-03-27 11:33 ` eregontp
  2021-03-27 21:51 ` [ruby-core:103065] " tenderlove
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: eregontp @ 2021-03-27 11:33 UTC (permalink / raw)
  To: ruby-core

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


@sawa I'd say first assignment to a named constant wins, just like for Module#name.

I agree with the feature.
I'd suggest `Module#namespace` for the name though.
For example, I'd say the namespace of `Process::Status` is `Process`.

`scope` feels general to me, and there are many other scopes, so I think namespace is a more precise term for it.

`namespace` is also the term used in https://github.com/ruby/ruby/blob/master/doc/syntax/modules_and_classes.rdoc#label-Modules

----------------------------------------
Feature #17753: Add Module#outer_scope
https://bugs.ruby-lang.org/issues/17753#change-91118

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)


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

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

* [ruby-core:103065] [Ruby master Feature#17753] Add Module#outer_scope
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
  2021-03-27  7:58 ` [ruby-core:103053] " sawadatsuyoshi
  2021-03-27 11:33 ` [ruby-core:103057] " eregontp
@ 2021-03-27 21:51 ` tenderlove
  2021-03-28  6:05 ` [ruby-core:103069] " sawadatsuyoshi
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: tenderlove @ 2021-03-27 21:51 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by tenderlovemaking (Aaron Patterson).

File 0001-Add-Module-namespace.patch added

Eregon (Benoit Daloze) wrote in #note-2:
> @sawa I'd say first assignment to a named constant wins, just like for Module#name.

Yes, this is what I would expect too (and implemented). 😄

> I agree with the feature.
> I'd suggest `Module#namespace` for the name though.
> For example, I'd say the namespace of `Process::Status` is `Process`.

Yes, this is a much better name.  I've updated the patch to use "namespace".


----------------------------------------
Feature #17753: Add Module#outer_scope
https://bugs.ruby-lang.org/issues/17753#change-91124

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103069] [Ruby master Feature#17753] Add Module#outer_scope
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (2 preceding siblings ...)
  2021-03-27 21:51 ` [ruby-core:103065] " tenderlove
@ 2021-03-28  6:05 ` sawadatsuyoshi
  2021-03-28 13:33 ` [ruby-core:103072] " jean.boussier
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: sawadatsuyoshi @ 2021-03-28  6:05 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by sawa (Tsuyoshi Sawada).


This feature is reminiscent of `Module.nesting`. The difference is that the former has dynamic scope and the latter lexical scope. Besides that, I do not see any reason to make them different in any way. What about returning an array of the nested modules (perhaps including the current one) rather than just the direct parent?

```ruby
module A; module B; class C; Module.nesting end end end # => [A::B::C, A::B, A]

A::B::C.outer_scope # => [A::B::C, A::B, A]
```


----------------------------------------
Feature #17753: Add Module#outer_scope
https://bugs.ruby-lang.org/issues/17753#change-91132

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103072] [Ruby master Feature#17753] Add Module#outer_scope
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (3 preceding siblings ...)
  2021-03-28  6:05 ` [ruby-core:103069] " sawadatsuyoshi
@ 2021-03-28 13:33 ` jean.boussier
  2021-04-10 10:35 ` [ruby-core:103371] [Ruby master Feature#17753] Add Module#namespace fxn
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: jean.boussier @ 2021-03-28 13:33 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by byroot (Jean Boussier).


> Besides that, I do not see any reason to make them different in any way

Well, if `Module.nesting` because of its scope semantic can't be chained. `Module.nesting.nesting` would be problematic.

The proposed feature is very easily chainable:

```ruby
A::B::C.namespace # => A::B
A::B::C.namespace.namespace # => A
```

So returning an array doesn't give anything that's not already achievable, and cause an array allocation that some users would rather avoid in some situations.

----------------------------------------
Feature #17753: Add Module#outer_scope
https://bugs.ruby-lang.org/issues/17753#change-91134

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103371] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (4 preceding siblings ...)
  2021-03-28 13:33 ` [ruby-core:103072] " jean.boussier
@ 2021-04-10 10:35 ` fxn
  2021-04-10 10:54 ` [ruby-core:103372] " fxn
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-10 10:35 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


I like the direction this is going towards, however, let me record some remarks for the archives.

Java has namespaces. Ruby does NOT have namespaces. That first sentence in the module docs, also present in books, is a super naive entry point to modules. But it is an abuse of language that later on you should correct. Ruby does not have syntax for types either.

A library like Zeitwerk or Active Support can take some licenses "you know what I mean" because they are libraries and they work on the assumption of projects structured in a certain way. But a programming language has to be consistent with itself. Module#constants is consistent, Module#namespace is not (with the current model).

Ruby has storage (variables, constants, etc.), and objects. That is all, variables, constants, and objects are totally decoupled except for the fact that you get a name in the first assignment. A name that does not reflect the nesting, that does not mean the object is reachable via that constant path, and that some classes change by overriding the `name` method. It is just a string.

So, if Ruby core wants to go in this direction and contribute to normalize a bit the mental model, I am onboard. But we have to be conscious that this is introducing something that is going to leak some way or another.




----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91464

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103372] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (5 preceding siblings ...)
  2021-04-10 10:35 ` [ruby-core:103371] [Ruby master Feature#17753] Add Module#namespace fxn
@ 2021-04-10 10:54 ` fxn
  2021-04-10 20:45 ` [ruby-core:103382] " fxn
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-10 10:54 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


 Let me add some edge cases that are possible, also for the archives:

```ruby
module M
  module N
  end
end

M::N.namespace # => A::B::C, parent module name does not match
```

```ruby
M.namespace # => M, module is namespace of itself
```

```ruby
M::N.namespace # => M
M.namespace    # => N, cycles of arbitrary depth
```

```ruby
M::N.namespace # => The module that was once in M has been garbage collected
```

I am sure I can come with more if I think more about it.

The Ruby model of this is extremely flexible and decoupled, and that is the public interface. Constant assignment, constants API, instantiation of anonymous modules, etc.


----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91465

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103382] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (6 preceding siblings ...)
  2021-04-10 10:54 ` [ruby-core:103372] " fxn
@ 2021-04-10 20:45 ` fxn
  2021-04-12 15:28 ` [ruby-core:103405] " tenderlove
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-10 20:45 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


Also, in case my comments above are too genric, let's take the use case in the description of the ticket:

> I can do A::B::C.outer_scope.constants to find the list of "sibling" constants to C.

Let's consider

```ruby
module A
  module B
    class C; end
    class D; end
  end 
end

module X
  Y = A::B::C
  Z = 1
end
```

In what sense is `A::B::D` a sibling of `A::B::C` and `X::Z` is not?

If our input is a class object, as in the `ObjectSpace` example, you have no information that allows you to jump from it to its possibly multiple places in which the object may be stored. And the original constant may be gone, those places can be elsewhere (as it happens with stale class objects cached during Rails initialization after a reload).

On the other hand, if you are in a very specific situation where you can assume that loop makes sense for all `k`, you can always `name.sub(/::\w+$/, '')` and `const_get`, modulus details. In a project, in a library, you may have constraints in place that you can exploit. In Ruby, the language, you don't.


----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91475

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103405] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (7 preceding siblings ...)
  2021-04-10 20:45 ` [ruby-core:103382] " fxn
@ 2021-04-12 15:28 ` tenderlove
  2021-04-12 17:29 ` [ruby-core:103409] " eregontp
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: tenderlove @ 2021-04-12 15:28 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by tenderlovemaking (Aaron Patterson).


> Yes, c.name is "X::C", but as I said above, that is just a string.

It's also a way to inform the user where that constant lives.  The contents of the string have meaning.

> On the other hand, if you are in a very specific situation where you can assume that loop makes sense for all k, you can always name.sub(/::\w+$/, '') and const_get, modulus details.

This would work if I could trust the `name` method on a class (I can't, especially in a Rails project).

Of course there are some edge cases with redefinition, but since the "namespace" method would line up with what the "name" method is supposed to return, I think it would be easy to understand the behavior.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91499

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103409] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (8 preceding siblings ...)
  2021-04-12 15:28 ` [ruby-core:103405] " tenderlove
@ 2021-04-12 17:29 ` eregontp
  2021-04-13  9:29 ` [ruby-core:103417] " fxn
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: eregontp @ 2021-04-12 17:29 UTC (permalink / raw)
  To: ruby-core

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


I think those edge cases are pretty rare.
Module#namespace would refer to the lexical parent when the module is created (with `module Name`) or when first assigned to a constant (`Name = Module.new`).

The first example of https://bugs.ruby-lang.org/issues/17753#note-8 would already need extremely contrived code like:
```ruby
module A
  module B
    module C
    end
  end
end

module M
  N = A::B::C
  module N
  end
  p N.namespace
end
```
and even then the value could still be useful.

In the end, the exact same caveats exist for Module#name and yet it's fine in practice.

A module is a namespace of constants.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91504

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103417] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (9 preceding siblings ...)
  2021-04-12 17:29 ` [ruby-core:103409] " eregontp
@ 2021-04-13  9:29 ` fxn
  2021-04-13  9:37 ` [ruby-core:103418] " fxn
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-13  9:29 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


> It's also a way to inform the user where that constant lives. The contents of the string have meaning.

The numerous people that have had to deal with stale objects in Rails for years know that is not entirely true. The class objects have a name, but that constant path no longer gives you the object at hand, but some another object that happens to have the same name.

Benoit, but a programming language is a formal system. It has to define things that are consistent with its model! It does not matter in my view if the examples are statistically rare. They are only ways to demonstrate the definition does not match the way Ruby works.

> A module is a namespace of constants.

Yes, but it is dynamic because of const_set and remove_const, and your APIs and concepts need to reflect that.

If you wanted namespaces, you'd have a different programming language where everything is consistent with that concept. But Ruby is not that way.

Same way Ruby does not have types. Admin::User is not a type (we all in this thread know that), it is a constant path. That is all you got, constants and objects, and constants API.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91508

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103418] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (10 preceding siblings ...)
  2021-04-13  9:29 ` [ruby-core:103417] " fxn
@ 2021-04-13  9:37 ` fxn
  2021-04-13  9:46 ` [ruby-core:103419] " fxn
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-13  9:37 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


BTW, we were discussing yesterday with Aaron that the flag I am raising is about the name `namespace`. What we are defining here is, given a class object is:

1. If the class object is anonymous, return `nil`.
2. Othwerwise, it was assigned to a constant at least once. Let `namespace` be the module object that stored that constant at assignment time if it is an alive object, `nil` if the original object is gone (possible depending on whether the reference is weak or not).

We do not have a good name for that.

Another thing Aaron is exploring is to define `Module#namespaces`, which would return all modules that store the class object in one of their constants. That is a bit closer to the Ruby model, I believe.


----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91509

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103419] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (11 preceding siblings ...)
  2021-04-13  9:37 ` [ruby-core:103418] " fxn
@ 2021-04-13  9:46 ` fxn
  2021-04-13 10:01 ` [ruby-core:103420] " fxn
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-13  9:46 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


To me, the ability of a namespace being namespace of itself

```ruby
m = Module.new
m::M = m
```

is one clear indicator that the name is not quite right. That is not the kind of property you expect a namespace to have. And it is not quite right because we are dealing with storage and objects. In the world of storage and objects that examples squares perfectly, there is no surprise.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91510

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103420] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (12 preceding siblings ...)
  2021-04-13  9:46 ` [ruby-core:103419] " fxn
@ 2021-04-13 10:01 ` fxn
  2021-04-13 10:57 ` [ruby-core:103422] " eregontp
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-13 10:01 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


Oh, let me say something explicitly: You guys are Ruby committers, you are the ones that have the vision for what makes sense in the language.

I am raising a flag because this does not square to me, and makes me feel it is introducing a leaking abstraction not backed by the language model. It is an abstraction you could tolerate in Active Support with documented caveats, but not one that I personally see in Ruby itself.

However, if once the feedback has been listened to you believe this API squares with your vision of Ruby, by all means go ahead :).


----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91511

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103422] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (13 preceding siblings ...)
  2021-04-13 10:01 ` [ruby-core:103420] " fxn
@ 2021-04-13 10:57 ` eregontp
  2021-04-13 11:50 ` [ruby-core:103424] " fxn
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: eregontp @ 2021-04-13 10:57 UTC (permalink / raw)
  To: ruby-core

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


I see, the name `namespace` is what we're disagreeing on.
Maybe you have another suggestion for the name of that method?

Maybe `outer_module`/`outer_scope` would work too, but I feel `namespace` is nicer.
All these 3 names imply some kind of lexical relationship. And even though that can be broken, in most cases it is respected and the intent of the user using this new method is clearly to go one step up in the lexical relationship.
So we should mention in the docs this might return unusual results for e.g. anonymous modules that are later assigned to a constant.

FWIW internally that's named "lexical parent module" in TruffleRuby, but that doesn't make a nice method name.
Indeed, it's not always "lexical" but in the vast majority of cases the intent is that and we would say `A::B` is `namespaced` or `defined under` (`rb_define_module_under)` module/class `A`.

The way I see it is modules are the closest thing to a namespace that Ruby has. And therefore Module#namespace feels natural to me.
From the other direction, I agree namespaces often have different/stricter semantics than Ruby modules in other languages.
Yet I think it's OK to have a slightly different meaning for namespace in Ruby, and that seems already established in docs.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91513

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103424] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (14 preceding siblings ...)
  2021-04-13 10:57 ` [ruby-core:103422] " eregontp
@ 2021-04-13 11:50 ` fxn
  2021-04-13 16:35 ` [ruby-core:103433] " fxn
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-13 11:50 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


The lexical parent module happens to be just the object from which you set the name, which does not even reflect the scope/nesting at assignment time (as you know):

```ruby
module A::B
  module X::Y
    class C
      name # => X::Y::C
    end
  end
end
```

Yeah, we see it differently. There, I only see a constant assignment. You see it like "most of the time, you can think of it that way because that's how most of Ruby looks like". That difference in points of view is fine :).

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91517

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103433] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (15 preceding siblings ...)
  2021-04-13 11:50 ` [ruby-core:103424] " fxn
@ 2021-04-13 16:35 ` fxn
  2021-04-17  7:27 ` [ruby-core:103493] " mame
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-13 16:35 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


BTW, you all know AS has this concept right? https://github.com/rails/rails/blob/f1e00f00295eb51a64a3008c7b1f4c4f46e902e3/activesupport/lib/active_support/core_ext/module/introspection.rb#L20-L37

We say "according to its name" and case closed.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91527

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103493] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (16 preceding siblings ...)
  2021-04-13 16:35 ` [ruby-core:103433] " fxn
@ 2021-04-17  7:27 ` mame
  2021-04-17  8:04 ` [ruby-core:103496] " fxn
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: mame @ 2021-04-17  7:27 UTC (permalink / raw)
  To: ruby-core

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


This ticket was discussed on the dev meeting. @matz said that (1) the use case is not clear to him, and that (2) he wants to keep the keyword `namespace` for another feature in future. `outer_scope` is also weird because the return value is not a "scope".

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91589

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:103496] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (17 preceding siblings ...)
  2021-04-17  7:27 ` [ruby-core:103493] " mame
@ 2021-04-17  8:04 ` fxn
  2022-07-01  6:52 ` [ruby-core:109108] " ioquatix (Samuel Williams)
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn @ 2021-04-17  8:04 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by fxn (Xavier Noria).


In my view, the way to implement the use case that matches Ruby is to go downwards.

Module has many constants, that is the Ruby model, so instead of

```ruby
ObjectSpace.each_object(Class) do |k|
  k.outer_scope.constants
end
```

you'd write

```ruby
ObjectSpace.each_object(Module) do |mod|
  mod.constants.each do |cname|
    # Do something with cname.
  end
end
```

Alternatively, Recurse starting at `Object` (would miss anonymous modules with constants).

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-91592

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:109108] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (18 preceding siblings ...)
  2021-04-17  8:04 ` [ruby-core:103496] " fxn
@ 2022-07-01  6:52 ` ioquatix (Samuel Williams)
  2022-07-01 16:13 ` [ruby-core:109111] " sawa (Tsuyoshi Sawada)
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: ioquatix (Samuel Williams) @ 2022-07-01  6:52 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by ioquatix (Samuel Williams).


@tenderlovemaking what about some kind of "uplevel" concept for name:

```ruby
class A::B::C::MyClass; end

A::B::C::MyClass.name(0) # -> "MyClass"
A::B::C::MyClass.name(1) # -> "C::MyClass"
A::B::C::MyClass.name(-1) # -> "A::B::C"
A::B::C::MyClass.name(-2) # -> "A::B"
```

etc

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-98255

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:109111] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (19 preceding siblings ...)
  2022-07-01  6:52 ` [ruby-core:109108] " ioquatix (Samuel Williams)
@ 2022-07-01 16:13 ` sawa (Tsuyoshi Sawada)
  2022-07-02  0:03 ` [ruby-core:109112] " ioquatix (Samuel Williams)
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: sawa (Tsuyoshi Sawada) @ 2022-07-01 16:13 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by sawa (Tsuyoshi Sawada).


ioquatix (Samuel Williams) wrote in #note-21:
> ```ruby
> class A::B::C::MyClass; end
> 
> A::B::C::MyClass.name(0) # -> "MyClass"
> A::B::C::MyClass.name(1) # -> "C::MyClass"
> A::B::C::MyClass.name(-1) # -> "A::B::C"
> A::B::C::MyClass.name(-2) # -> "A::B"
> ```

What is the rule behind what the argument represents? To me, your four examples except for the first one seem to suggest:

1. The nesting levels (achieved by separating the full name  by `::`) can be referred to by an index as if they were placed in an array. 
2. a. If the argument is negative, then remove the nesting levels from the one indexed by the argument up to the last one.
 b. If the argument is non-negative, then remove the nesting levels from the first one up to the one indexed by the argument.
3. Join the remaining nesting levels with `::`.

But, then I would expect:

```ruby
A::B::C::MyClass.name(0) # -> "B::C::MyClass"
```

contrary to what you wrote.

What is your intended logic? Is it coherent? And does that provide a way to get `"B::C::MyClass"`?

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-98258

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:109112] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (20 preceding siblings ...)
  2022-07-01 16:13 ` [ruby-core:109111] " sawa (Tsuyoshi Sawada)
@ 2022-07-02  0:03 ` ioquatix (Samuel Williams)
  2022-07-02  5:01 ` [ruby-core:109114] " sawa (Tsuyoshi Sawada)
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: ioquatix (Samuel Williams) @ 2022-07-02  0:03 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by ioquatix (Samuel Williams).


```ruby
class Class
  def name(offset = nil)
    return super() unless offset

    parts = super().split('::')

    if offset >= 0
        parts = parts[(parts.size - 1 - offset)..-1]
    else
        parts = parts[0...(parts.size + offset)]
    end

    return parts.join('::')
  end
end

module A
    module B
        module C
            class MyClass
            end
        end
    end
end

pp A::B::C::MyClass.name(0) # -> "MyClass"
pp A::B::C::MyClass.name(1) # -> "C::MyClass"
pp A::B::C::MyClass.name(-1) # -> "A::B::C"
pp A::B::C::MyClass.name(-2) # -> "A::B"
```

Something like this.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-98259

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:109114] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (21 preceding siblings ...)
  2022-07-02  0:03 ` [ruby-core:109112] " ioquatix (Samuel Williams)
@ 2022-07-02  5:01 ` sawa (Tsuyoshi Sawada)
  2022-07-03 23:41 ` [ruby-core:109129] " ioquatix (Samuel Williams)
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: sawa (Tsuyoshi Sawada) @ 2022-07-02  5:01 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by sawa (Tsuyoshi Sawada).


@ioquatix (Samuel Williams)

The non-negative part of your code looks pretty much convoluted. To simplify your code (and define it on `Module` rather than on `Class`), it would be essentially this:

```ruby
Module.prepend(Module.new do
  def name(offset = nil)
    return super() unless offset

    super().split('::').then do |parts|
      if offset >= 0
        parts.last(offset + 1)
      else
        parts[...offset]
      end
    end.join('::')
  end
end)
```

This indicates that you are essentially using the argument `offset`:

* to specify the **number** of elements when `offset` is non-negative, and
* to specify the ending **position** (index) of the elements otherwise.

which is incoherent. At least to me, your proposal is in fact difficult to understand because of this. I think it should be unified so that either `offset` expresses the number all the way down, or it does the position all the way down.


----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-98260

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:109129] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (22 preceding siblings ...)
  2022-07-02  5:01 ` [ruby-core:109114] " sawa (Tsuyoshi Sawada)
@ 2022-07-03 23:41 ` ioquatix (Samuel Williams)
  2022-07-04  1:42 ` [ruby-core:109131] " austin (Austin Ziegler)
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: ioquatix (Samuel Williams) @ 2022-07-03 23:41 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by ioquatix (Samuel Williams).


@sawa Thanks for your feedback and the improved code.

Based on my own needs and other code (see <https://apidock.com/rails/ActiveSupport/Inflector/demodulize> and <https://apidock.com/rails/ActiveSupport/Inflector/deconstantize> for example) I see two main use cases:

(1) Get some part of the namespace starting from the left.
(2) Get some part of the class name starting from the right.

To me it's consistent within the requirements of solving those two problems and maps nicely to negative and non-negative integers respectively.

I realise that between the negative and non-negative offset, there is no continuity but this is by design to satisfy user needs rather than theoretical purity. If you have a better idea, please share it!

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-98270

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:109131] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (23 preceding siblings ...)
  2022-07-03 23:41 ` [ruby-core:109129] " ioquatix (Samuel Williams)
@ 2022-07-04  1:42 ` austin (Austin Ziegler)
  2023-02-08  3:41 ` [ruby-core:112273] " shioyama (Chris Salzberg) via ruby-core
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: austin (Austin Ziegler) @ 2022-07-04  1:42 UTC (permalink / raw)
  To: ruby-core

Issue #17753 has been updated by austin (Austin Ziegler).


ioquatix (Samuel Williams) wrote in #note-25:
> To me it's consistent within the requirements of solving those two problems and maps nicely to negative and non-negative integers respectively. I realise that between the negative and non-negative offset, there is no continuity but this is by design to satisfy user needs rather than theoretical purity. If you have a better idea, please share it!

Since name doesn’t currently accept any arguments, why not make it a keyword instead of a simple integer?

```ruby
A::B::C::MyClass.name(tail: 1) # C::MyClass
A::B::C::MyClass.name(head: 1) # A::B::C
```

I don’t know what the name of the keywords should be.


----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-98272

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


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

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

* [ruby-core:112273] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (24 preceding siblings ...)
  2022-07-04  1:42 ` [ruby-core:109131] " austin (Austin Ziegler)
@ 2023-02-08  3:41 ` shioyama (Chris Salzberg) via ruby-core
  2023-02-08  7:54 ` [ruby-core:112277] " fxn (Xavier Noria) via ruby-core
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: shioyama (Chris Salzberg) via ruby-core @ 2023-02-08  3:41 UTC (permalink / raw)
  To: ruby-core; +Cc: shioyama (Chris Salzberg)

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


This has been quiet for a while, but despite the reservations expressed I'd really like to see it implemented.

I don't personally really like `namespace` as a name either, because of its usage in other places. It's been mentioned, but what exactly is wrong with `module_parents`, the same method ActiveSupport uses?

@fxn

> Yes, c.name is "X::C", but as I said above, that is just a string.

It's a string, yes, but it also includes some rules about _what_ to return _when_ that I think are relevant to your concerns about edge cases.

I think any implementation of this method should be fully consistent with `Module#name`. That means also encompassing names that are temporary (where the root is anonymous).

Just so we're all on the same page:

```ruby
mod = Module.new
mod.name
#=> nil

mod::Foo = Module.new
mod::Foo.name
#=> "#<Module:0x0000000106471d80>::Foo"
```

`"#<Module:0x0000000106471d80>::Foo"` is `mod::Foo`'s "temporary name". We can assign another module under an anonymous root to it and it will not change:

```ruby
other_mod = Module.new
other_mod::Bar = mod::Foo

other_mod::Bar
#=> "#<Module:0x0000000106471d80>::Foo"
```

So temporary names are "sticky" as long as the module doesn't have a permanent name. Once it has a permanent name, that name does not change regardless of assignment to other toplevel-rooted constants.

So we have some rules for how `Module#name` can and cannot change:

1. A module's permanent name, once assigned, cannot be re-assigned. So although you can nest the same constant in many places in many ways, the `name`, once attached to a permanent root, will not change.
2. A module's temporary name, once assigned, cannot be re-assigned except to a permanent name. So you can assign another name from an anonymous namespace, the module's original temporary name sticks and only changes when/if it gets a permanent name. 

I think these rules give us everything we need to define a method that returns the set of module objects in `name` as an array, and I think this would be a very useful method to have.

Extended to anonymous roots, I would expect this (I'm using `namespace` here because that's the current name we're talking about, I don't love it but just to avoid confusion):

```ruby
mod = Module.new
mod::Foo = Module.new

mod::Foo.name
#=> "#<Module:0x0000000106471d80>::Foo"

mod::Foo.namespace
#=> [<Module:0x0000000106471d80>::Foo, <Module:0x0000000106471d80>]

other_mod = Module.new
other_mod::Bar = mod::Foo
other_mod::Bar.namespace
#=> [<Module:0x0000000106471d80>::Foo, <Module:0x0000000106471d80>]

Bar = mod
mod::Foo.namespace
#=> [Bar::Foo, Foo]

Baz = mod
Baz::Foo.namespace
#=> [Bar::Foo, Foo]
```

This is entirely consistent with how `name` works, and I think is in fact a very natural complement to it. Since conventions are exactly the same, there is no need for any additional "rules" to cover the edge cases above.

As an implementation, this is fully determined, consistent with an existing pattern (`Module#name`) and works as expected for most common use cases.

@mame

> the use case is not clear to him

It's been mentioned above, but [ActiveSupport](https://github.com/rails/rails/blob/dcd8f37bc63d46f28aa55e6891b03a0b0b73e497/activesupport/lib/active_support/core_ext/module/introspection.rb#L39-L62) and other libraries use `mod.name.split("::")` all over the place to go from something they can _see_ (`Module#name`) to something they can _use_ (actual module objects). This has always seemed extremely clumsy to me; Ruby generated the `name` from the module objects, but it will only give you the "trace" of them, not the actual living things.

Personally, I've been recently working with anonymous-rooted namespaces (like `mod` and `mod::Foo` above) and the inability to get the root of a module is yet more problematic, because `name.split("::")` and `constantize` don't work in that context. I'd love to see this happen, under any name that seems appropriate.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-101703

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


-- 
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/

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

* [ruby-core:112277] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (25 preceding siblings ...)
  2023-02-08  3:41 ` [ruby-core:112273] " shioyama (Chris Salzberg) via ruby-core
@ 2023-02-08  7:54 ` fxn (Xavier Noria) via ruby-core
  2023-02-08 10:01 ` [ruby-core:112285] " fxn (Xavier Noria) via ruby-core
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: fxn (Xavier Noria) via ruby-core @ 2023-02-08  7:54 UTC (permalink / raw)
  To: ruby-core; +Cc: fxn (Xavier Noria)

Issue #17753 has been updated by fxn (Xavier Noria).


Yeah, I believe the feature makes sense and can be useful, and the proposed implementation that keeps a pointer is well-defined (vs what AS does). Also consistent with `Module#name`, as you said.

My observations above were more related to the name `namespace` I think, because we are defining "the class or module object that holded the constant to which I was initially assigned, if any". That is weaker.


Regarding your proposal, in English would be `parent_module` right?

Let me add something, this is practical, but the Ruby model suffers just a little bit in my view. Let me explain.

To me:

```ruby
module M
  X = String.new
end

module N
  X = Module.new
end
```

are essentially the same, Ruby objects stored in places. As we all know, the Ruby model is quite unconstrained, which makes it beautiful, but also weaker in a logical sense.

So, there is a part of me that believes for consistency the string object should also respond to `parent_module`, which is a weird derivation. (I am playing reductio at absurdum here, no proposing that!). 

However, maybe in this case practicality can win over a pure and spherical language model, I don't know :).

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-101709

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


-- 
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/

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

* [ruby-core:112285] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (26 preceding siblings ...)
  2023-02-08  7:54 ` [ruby-core:112277] " fxn (Xavier Noria) via ruby-core
@ 2023-02-08 10:01 ` fxn (Xavier Noria) via ruby-core
  2023-02-09  8:02 ` [ruby-core:112295] " shioyama (Chris Salzberg) via ruby-core
  2023-02-10  0:48 ` [ruby-core:112316] " shioyama (Chris Salzberg) via ruby-core
  29 siblings, 0 replies; 31+ messages in thread
From: fxn (Xavier Noria) via ruby-core @ 2023-02-08 10:01 UTC (permalink / raw)
  To: ruby-core; +Cc: fxn (Xavier Noria)

Issue #17753 has been updated by fxn (Xavier Noria).


Let me reword that last remark about "the Ruby model suffers just a little bit".

Ruby objects and variables behave the same. But constants are not as orthogonal and generic:

1. When you assign an integer to a constant, it's just storage. If you assign a class or module object with a name, it's just storage. However, assigning an anonymous class or module object changes the state, it has a side-effect that is only programmed for these objects.
2. The `class` and `module` keywords perform constant assignments.

So, "suffer" is not an exact word for what I have in mind. I'd say this change would accentuate an already existing asimmetry, and in a way that is consitent with `Module#name`. This is not bad, it goes in a consistent direction.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-101717

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


-- 
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/

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

* [ruby-core:112295] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (27 preceding siblings ...)
  2023-02-08 10:01 ` [ruby-core:112285] " fxn (Xavier Noria) via ruby-core
@ 2023-02-09  8:02 ` shioyama (Chris Salzberg) via ruby-core
  2023-02-10  0:48 ` [ruby-core:112316] " shioyama (Chris Salzberg) via ruby-core
  29 siblings, 0 replies; 31+ messages in thread
From: shioyama (Chris Salzberg) via ruby-core @ 2023-02-09  8:02 UTC (permalink / raw)
  To: ruby-core; +Cc: shioyama (Chris Salzberg)

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


> When you assign an integer to a constant, it's just storage. If you assign a class or module object with a name, it's just storage. However, assigning an anonymous class or module object changes the state, it has a side-effect that is only programmed for these objects.

That's a very interesting way to put it, I hadn't thought of it that way. And indeed those side-effects scale with the number of other classes and modules rooted in the thing that was named.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-101730

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


-- 
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/

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

* [ruby-core:112316] [Ruby master Feature#17753] Add Module#namespace
  2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
                   ` (28 preceding siblings ...)
  2023-02-09  8:02 ` [ruby-core:112295] " shioyama (Chris Salzberg) via ruby-core
@ 2023-02-10  0:48 ` shioyama (Chris Salzberg) via ruby-core
  29 siblings, 0 replies; 31+ messages in thread
From: shioyama (Chris Salzberg) via ruby-core @ 2023-02-10  0:48 UTC (permalink / raw)
  To: ruby-core; +Cc: shioyama (Chris Salzberg)

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


> Regarding your proposal, in English would be `parent_module` right?

My interpretation here, but to me "parent module" would signify the "parent thing that is a module" of the current thing (whatever that thing may be), whereas "module parent" would signify the "module's parent", implying the _parent_ could be anything (but kind of implying it is also a module).

English-wise as a method name either is possible, they just have slightly different emphasis. I suggested `module_parent` because it exists and is being used for the same thing, so there's a precedent, which might make it easier to agree on.

----------------------------------------
Feature #17753: Add Module#namespace
https://bugs.ruby-lang.org/issues/17753#change-101757

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Given code like this:

```ruby
module A
  module B
    class C; end
    class D; end
  end
end
```

We can get from `C` to `B` like `C.outer_scope`, or to `A` like
`C.outer_scope.outer_scope`.

I want to use this in cases where I don't know the outer scope, but I
want to find constants that are "siblings" of a constant.  For example,
I can do `A::B::C.outer_scope.constants` to find the list of "sibling"
constants to `C`.  I want to use this feature when walking objects and
introspecting.  For example:

```ruby
ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
```

I've attached a patch that implements this feature, and there is a pull request on GitHub [here](https://github.com/ruby/ruby/pull/4326).

---Files--------------------------------
0001-Add-Module-outer_scope.patch (5.93 KB)
0001-Add-Module-namespace.patch (5.89 KB)


-- 
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/

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

end of thread, other threads:[~2023-02-10  0:49 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-26 19:19 [ruby-core:103044] [Ruby master Feature#17753] Add Module#outer_scope tenderlove
2021-03-27  7:58 ` [ruby-core:103053] " sawadatsuyoshi
2021-03-27 11:33 ` [ruby-core:103057] " eregontp
2021-03-27 21:51 ` [ruby-core:103065] " tenderlove
2021-03-28  6:05 ` [ruby-core:103069] " sawadatsuyoshi
2021-03-28 13:33 ` [ruby-core:103072] " jean.boussier
2021-04-10 10:35 ` [ruby-core:103371] [Ruby master Feature#17753] Add Module#namespace fxn
2021-04-10 10:54 ` [ruby-core:103372] " fxn
2021-04-10 20:45 ` [ruby-core:103382] " fxn
2021-04-12 15:28 ` [ruby-core:103405] " tenderlove
2021-04-12 17:29 ` [ruby-core:103409] " eregontp
2021-04-13  9:29 ` [ruby-core:103417] " fxn
2021-04-13  9:37 ` [ruby-core:103418] " fxn
2021-04-13  9:46 ` [ruby-core:103419] " fxn
2021-04-13 10:01 ` [ruby-core:103420] " fxn
2021-04-13 10:57 ` [ruby-core:103422] " eregontp
2021-04-13 11:50 ` [ruby-core:103424] " fxn
2021-04-13 16:35 ` [ruby-core:103433] " fxn
2021-04-17  7:27 ` [ruby-core:103493] " mame
2021-04-17  8:04 ` [ruby-core:103496] " fxn
2022-07-01  6:52 ` [ruby-core:109108] " ioquatix (Samuel Williams)
2022-07-01 16:13 ` [ruby-core:109111] " sawa (Tsuyoshi Sawada)
2022-07-02  0:03 ` [ruby-core:109112] " ioquatix (Samuel Williams)
2022-07-02  5:01 ` [ruby-core:109114] " sawa (Tsuyoshi Sawada)
2022-07-03 23:41 ` [ruby-core:109129] " ioquatix (Samuel Williams)
2022-07-04  1:42 ` [ruby-core:109131] " austin (Austin Ziegler)
2023-02-08  3:41 ` [ruby-core:112273] " shioyama (Chris Salzberg) via ruby-core
2023-02-08  7:54 ` [ruby-core:112277] " fxn (Xavier Noria) via ruby-core
2023-02-08 10:01 ` [ruby-core:112285] " fxn (Xavier Noria) via ruby-core
2023-02-09  8:02 ` [ruby-core:112295] " shioyama (Chris Salzberg) via ruby-core
2023-02-10  0:48 ` [ruby-core:112316] " shioyama (Chris Salzberg) 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 read-only IMAP folder(s) and NNTP newsgroup(s).