[ruby-core:113940] [Ruby master Feature#19521] Support for `Module#name=` and `Class#name=`.
From:
"Eregon (Benoit Daloze) via ruby-core" <ruby-core@...>
Date:
2023-06-19 13:16:32 UTC
List:
ruby-core #113940
Issue #19521 has been updated by Eregon (Benoit Daloze).
ioquatix (Samuel Williams) wrote in #note-25:
> @Eregon I understand your point, but why would anyone do that? Isn't that kind of shooting yourself in the foot?
Well, even the docs and specs you added in that PR do that, it's inviting people to do it without telling them the big problem or protecting against it.
> And in any case, your example is already trivially possible without this PR/change:
Nope, that is fine (besides of course the bad idea to override a core constant, but at least you get a warning for that),
because the class of that object can in fact be referenced by `String` or at least it has been related to the constant path `String` at some point.
`Class.new.tap { _1.set_temporary_name "Foo" }` has never been related to the constant `Foo`. It's a lie.
And if you look at usages of `labeled_module`/`labeled_class` e.g. with `git grep labeled_ test` you can see for almost all of them it would be confusing to use `set_temporary_name`.
First they should use a non-valid constant name to make it clear e.g., what is currently labeled as `klass = EnvUtil.labeled_class("Parent")` cannot be accessed through `Parent` (otherwise good luck to write tests or any Ruby if you regularly cannot trust the output of a NoMethodError due to this new feature/bug).
----------------------------------------
Feature #19521: Support for `Module#name=` and `Class#name=`.
https://bugs.ruby-lang.org/issues/19521#change-103594
* Author: ioquatix (Samuel Williams)
* Status: Open
* Priority: Normal
----------------------------------------
See https://bugs.ruby-lang.org/issues/19450 for previous discussion and motivation.
[This proposal](https://github.com/ruby/ruby/pull/7483) introduces `Module#name=` (and thus also `Class#name=`) to set the temporary class name. The name assignment has no effect if the module/class already has a permanent name.
```ruby
c = Class.new do
self.name = "fake name"
end
c = Class.new
c.name = "fake name"
```
Alternatively, we could use `set_name`:
```ruby
Class.new do
set_name "fake_name"
end
```
Setting the name of a class changes its current name, irrespective of whether it's been assigned a permanent name, or has nested modules/classes which have cached a previous name. We might like to limit the cases where a name is set, e.g. only once, only if the name is nil, or only if it's not already permanent. There is no real harm in any of those options, just inconsistency.
## Example usage
The current Ruby test suite has code which shows the usefulness of this new method:
```ruby
def labeled_module(name, &block)
Module.new do
singleton_class.class_eval {
define_method(:to_s) {name}
alias inspect to_s
alias name to_s
}
class_eval(&block) if block
end
end
module_function :labeled_module
def labeled_class(name, superclass = Object, &block)
Class.new(superclass) do
singleton_class.class_eval {
define_method(:to_s) {name}
alias inspect to_s
alias name to_s
}
class_eval(&block) if block
end
end
module_function :labeled_class
```
The updated code would look like this:
```ruby
def labeled_module(name, &block)
Module.new do
self.name = name
class_eval(&block) if block
end
end
def labeled_class(name, superclass = Object, &block)
Class.new(superclass) do
self.name = name
class_eval(&block) if block
end
end
module_function :labeled_class
```
Because the name cannot be set as part of `.new`, we have to have a separate block to set the name, before calling `class_eval`. I think the ergonomics and performance of this are slightly worse than the [counter proposal](https://bugs.ruby-lang.org/issues/19520).
--
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/