ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: "myronmarston (Myron Marston)" <myron.marston@gmail.com>
To: ruby-core@ruby-lang.org
Subject: [ruby-core:58050] [ruby-trunk - Bug #8982] NoMethodError#message produces surprising output when #inspect is defined on an anonymous class
Date: Sun, 27 Oct 2013 11:59:48 +0900	[thread overview]
Message-ID: <redmine.journal-42631.20131027115947@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-8982.20131003152300@ruby-lang.org


Issue #8982 has been updated by myronmarston (Myron Marston).


nobu (Nobuyoshi Nakada) wrote:
> myronmarston (Myron Marston) wrote:
> > * It matters whether or not the first character in my `inspect` is a `#`.  If it's not, ruby appends the class's `#inspect` output to it.
> 
> '#' at the beginning is assumed the string is same as Object#inspect, otherwise its class name is appended since the string may not represent the class.

Ruby itself provides many classes whose definition of `inspect` does not include `#`.  Why cannot it not allow me to do the same?  Also, `#` at the beginning of the string being taken as a sign that it's the same string as `Object#inspect` would produce seems incredibly broken.  And I'm not sure why you care?  Why can't I define how my class is represented as a string?  Isn't that the point of `inspect`?

> > * It matters how long my `inspect` string is.  If it's less than 66 characters, it's used; if it's more than 65, it's discarded, and the default anonymous `#inspect` is used instead.
> 
> If the `inspect` string is too long, just ignore it and use default conersion method

Many of ruby's built-in classes can produce longer inspect strings than this.  (As an example:`([1] * 1000).inspect`).  Ignoring what a user has defined for `inspect` seems incredibly surprising and would be considered a bug by every ruby programmer I know (well, every ruby programmer I've shown this issue to, at least).

IMO, Ruby should either retain complete control over how objects represent themselves strings, or allow users to define how objects are represented as strings...but giving us the illusion that we can define how objects represent themselves as strings, and then not actually allowing that, is the worst possible outcome.

And this isn't just theoretical: I spent a couple hours a few weeks ago scratching my head, trying to figure out why in the world my object's `inspect` wasn't working.

----------------------------------------
Bug #8982: NoMethodError#message produces surprising output when #inspect is defined on an anonymous class
https://bugs.ruby-lang.org/issues/8982#change-42631

Author: myronmarston (Myron Marston)
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]
Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN


=begin
Given the following script:

 def raise_no_method_error_for_anonymous_class_with_inspect(&block)
   klass = Class.new do
     define_method(:inspect, &block)
   end

   begin
     instance = klass.new
     puts "#inspect output: #{instance.inspect} (#{instance.inspect.length} chars)"
     instance.undefined_method
   rescue NoMethodError => e
     puts e.message
   end

   puts
 end

 raise_no_method_error_for_anonymous_class_with_inspect do
   "#<MyAnonymousClass>"
 end

 raise_no_method_error_for_anonymous_class_with_inspect do
   "<MyAnonymousClass>"
 end

 raise_no_method_error_for_anonymous_class_with_inspect do
   "#<MyAnonymousClass #{'a' * 45}>"
 end

 raise_no_method_error_for_anonymous_class_with_inspect do
   "#<MyAnonymousClass #{'a' * 46}>"
 end

It produces the following output:

 #inspect output: #<MyAnonymousClass> (19 chars)
 undefined method `undefined_method' for #<MyAnonymousClass>

 #inspect output: <MyAnonymousClass> (18 chars)
 undefined method `undefined_method' for <MyAnonymousClass>:#<Class:0x1017270e8>

 #inspect output: #<MyAnonymousClass aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> (65 chars)
 undefined method `undefined_method' for #<MyAnonymousClass aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>

 #inspect output: #<MyAnonymousClass aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> (66 chars)
 undefined method `undefined_method' for #<#<Class:0x1017266e8>:0x101726698>

There are two surprising things here:

* It matters whether or not the first character in my `inspect` is a `#`.  If it's not, ruby appends the class's `#inspect` output to it.
* It matters how long my `inspect` string is.  If it's less than 66 characters, it's used; if it's more than 65, it's discarded, and the default anonymous `#inspect` is used instead.

Both of these things are extremely surprising and seem very arbitrary and inconsistent.

I brought this up on ruby parley and @charliesome was kind enough to point me to the code that's the source of this issue:

((<error.c#L1091-1104|URL:https://github.com/ruby/ruby/blob/870dc20922d1ab0b628d24e64e971e8eb77ecd61/error.c#L1091-1104>))

So it looks intentional, but I think this is a bug.
=end



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

  parent reply	other threads:[~2013-10-27  3:32 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-03  6:23 [ruby-core:57629] [ruby-trunk - Bug #8982][Open] NoMethodError#message produces surprising output when #inspect is defined on an anonymous class myronmarston (Myron Marston)
2013-10-17 15:13 ` [ruby-core:57920] [ruby-trunk - Bug #8982] " nobu (Nobuyoshi Nakada)
2013-10-18  4:57 ` [ruby-core:57929] " alexeymuranov (Alexey Muranov)
2013-10-27  2:59 ` myronmarston (Myron Marston) [this message]
2014-09-12  6:47 ` [ruby-core:64990] " myron.marston
2019-08-15 23:56 ` [ruby-core:94376] [Ruby master Bug#8982] " merch-redmine

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-42631.20131027115947@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).