Project

General

Profile

Actions

Feature #21389

closed

Simplify Set#inspect output

Feature #21389: Simplify Set#inspect output

Added by jeremyevans0 (Jeremy Evans) 7 months ago. Updated 15 days ago.

Status:
Closed
Target version:
-
[ruby-core:122355]

Description

As Set is now a core collection class, it should have special inspect output. Ideally, inspect output should be suitable to eval, similar to array and hash (assuming the elements are also suitable to eval):

set = Set[1, 2, 3]
eval(set.inspect) == set # should be true

The simplest way to do this is to use the Set[] syntax:

Set[1, 2, 3].inspect
# => "Set[1, 2, 3]"

I've submitted a pull request that implements this: https://github.com/ruby/ruby/pull/13488

The pull request deliberately does not use any subclass name in the output, similar to array and hash. I think it is more important that users know they are dealing with a set than which subclass:

Class.new(Set)[]
# PR does: Set[]
#     not: #<Class:0x00000c21c78699e0>[]

However, it's easy to change the PR to use a subclass name if that is desired.


Related issues 1 (0 open1 closed)

Related to Ruby - Bug #21377: core Set#inspect does not use inherited class nameClosedActions

Updated by Eregon (Benoit Daloze) 7 months ago Actions #1

  • Related to Bug #21377: core Set#inspect does not use inherited class name added

Updated by Eregon (Benoit Daloze) 7 months ago Actions #2 [ruby-core:122363]

Per https://bugs.ruby-lang.org/issues/21377#note-5 (that issue should have been linked BTW, I added it),
I strongly believe showing Set[1, 2, 3] instead of MySet[1, 2, 3] for an instance of MySet would be a mistake.

Array and Hash don't show the class name at all, then sure obviously they don't show the subclass name either.
No inspect, if it shows the class name, should ever show the wrong class name, i.e., not obj.class.inspect, that would just be intentional confusion and there is no reason for that.

The example with an anonymous subclass is unrepresentative of realistic usages so hardly matters in comparison.

BTW here is an example of a core class showing the subclass name:

class MyModule < Module; end
p MyModule.new # => #<MyModule:0x00007f4e318e3ad8>

Updated by matz (Yukihiro Matsumoto) 7 months ago Actions #3 [ruby-core:122437]

I prefer Set[1, 2, 3] to #<Set: {1, 2, 3}>. And the name of the subclass should be printed, e.g. MySet[1, 2, 3].

Matz.

Updated by jeremyevans (Jeremy Evans) 6 months ago Actions #4

  • Status changed from Open to Closed

Applied in changeset git|3a9c091cf393e8a9c4e4b93d4216f2be3678e488.


Simplify Set#inspect output

As Set is now a core collection class, it should have special inspect
output. Ideally, inspect output should be suitable to eval, similar
to array and hash (assuming the elements are also suitable to eval):

set = Set[1, 2, 3]
eval(set.inspect) == set # should be true

The simplest way to do this is to use the Set[] syntax.

This deliberately does not use any subclass name in the output,
similar to array and hash. It is more important that users know they
are dealing with a set than which subclass:

Class.new(Set)[]

this does: Set[]

not: #Class:0x00000c21c78699e0[]

This inspect change breaks the power_assert bundled gem tests, so
add power_assert to TEST_BUNDLED_GEMS_ALLOW_FAILURES in the workflows.

Implements [Feature #21389]

Updated by zverok (Victor Shepelev) 15 days ago Actions #5 [ruby-core:124184]

  • Status changed from Closed to Open
  • Assignee set to jeremyevans0 (Jeremy Evans)

Just noticed that on the latest master subclasses #inspect didn't change (unlike what @matz (Yukihiro Matsumoto) suggests here: https://bugs.ruby-lang.org/issues/21389#note-3):

class MySet < Set
end

p Set[1, 2, 3]   #=> Set[1, 2, 3]
p MySet[1, 2, 3] #=> #<MySet: {1, 2, 3}>

Is it deliberate? (Working on docs for the new release.)

Updated by jeremyevans0 (Jeremy Evans) 15 days ago Actions #6 [ruby-core:124189]

  • Status changed from Open to Closed

zverok (Victor Shepelev) wrote in #note-5:

Just noticed that on the latest master subclasses #inspect didn't change (unlike what @matz (Yukihiro Matsumoto) suggests here: https://bugs.ruby-lang.org/issues/21389#note-3):

class MySet < Set
end

p Set[1, 2, 3]   #=> Set[1, 2, 3]
p MySet[1, 2, 3] #=> #<MySet: {1, 2, 3}>

Is it deliberate? (Working on docs for the new release.)

Yes, this is deliberate for backwards compatibility. Discussion in the GitHub PR: https://github.com/ruby/ruby/pull/15228

If you subclass from Set::CoreSet (which avoids adding backwards compatibility), the #inspect output follows the new Set output: https://github.com/ruby/ruby/pull/15228#discussion_r2539497376

The basic approach is that as much as possible, subclasses of Set behave as they did behavior. The only cases where the behavior isn't backwards compatible for Set subclasses is if the related methods accessed @hash (which no longer exists). In cases where @hash was accessed in stdlib Set, the backwards compatibility methods generally call super or another method.

Unless you need backwards compatibility with stdlib Set, I recommend subclassing from Set::CoreSet instead of Set.

Updated by zverok (Victor Shepelev) 15 days ago Actions #7 [ruby-core:124193]

@jeremyevans0 (Jeremy Evans) Thank you for the clarification. I'll try to consider adjusting the docs to reflect the design.

Actions

Also available in: PDF Atom