Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve documentation for Object#to_s and #inspect #9974

Merged

Conversation

straight-shoota
Copy link
Member

This patch changes the method definitions as proposed in #9966 and adds some additional notes.

The part about ambigouity of collection members is removed because that's not generically relevant for #inspect but for individual implementations such as Array#inspect. So I added a short note about it there.
It does not need to be repeated for every collection type.

Resolves #9966

This patch changes the method definitions as proposed in crystal-lang#9966 and adds some
additional notes.

The part about ambigouity of collection members is removed because that's not
generically relevant for `#inspect` but for individual implementations such as
`Array#inspect`. So I added a short note about it there.
It does not need to be repeated for every collection type.
src/object.cr Outdated Show resolved Hide resolved
src/array.cr Outdated Show resolved Hide resolved
src/object.cr Outdated Show resolved Hide resolved
@@ -1930,6 +1930,17 @@ class Array(T)
self
end

# Prints a nicely readable and concise string representation of this array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Prints a nicely readable and concise string representation of this array
# Prints a readable and concise string representation of this array

Let's avoid subjective language :) Ditto all the other instances.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "nicely" fits very well here. Just "readable" doesn't cut it. Of course, it should be readable. But so does #inspect. This one should be a nice, informal representation.

src/array.cr Outdated Show resolved Hide resolved
src/object.cr Outdated Show resolved Hide resolved
src/object.cr Outdated Show resolved Hide resolved
src/object.cr Outdated Show resolved Hide resolved
src/object.cr Outdated
# identical environment) is an ideal representation. It doesn't need to be
# actual code that compiles, but a resemblance is recommended.
# When this is not possible (for example for non-printable internal state)
# another useful description will do.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's be honest, this is a lie. It's true for literal'ish values, but beyond that the representation never even tries represent valid code. The default implementations for Reference and Struct make a good example of my point here. You wouldn't want the inspect representation to be like SomeStruct.new(a: ..., b: ...) as that's noisy and a little weird.

So I'm not sure this is true for people that are not standard library/compiler developers like us. You don't work much with "custom" objects that are literals elsewhere.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the wording could be a bit relaxed, but in general I think it's a good idea to try to print Crystal expressions. That's concise and unambiguous. Struct#inspect actually isn't far from Crystal code.
Simple structs/classes which are just containers for a vew ivars are already covered by the respective default implementations. These notes are particularly relevant for more advanced types. For example custom collection types. They can actually use array-like or hash-like literals. HTTP::Params{"foo" => "bar"} would be a perfect inspect representation. Currently, it's more bulky: HTTP::Params(@raw_params={"foo" => ["bar"]}). That's an example from stdlib but you have such types in shards, too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also not entirely happy with this wording, but it's more of style than anything else. Perhaps we can pick a couple of (good) examples from the stdlib instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't add a suggestion to the entire block, so here it goes in plain 🤷

  # Prints to *io* an unambiguous and information-rich string representation of this
  # object, typically intended for developers.
  #
  # It is similar to `#to_s(IO)`, but often provides more information. Ideally, it should
  # contain sufficient information to be able to recreate an object with the same value
  # (given an identical environment).
  #
  # For types that don't provide a custom implementation of this method,
  # default implementation delegates to `#to_s(IO)`. This said, it is advisable to 
  # have an appropriate `#inspect` implementation on every type. Default
  # implementations are provided by `Struct#inspect` and `Reference#inspect`.
  #
  # `::p` and `::p!` use this method to print an object in `STDOUT`.

src/object.cr Outdated Show resolved Hide resolved
src/object.cr Outdated Show resolved Hide resolved
Copy link
Member

@sdogruyol sdogruyol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @straight-shoota 🙏

src/object.cr Outdated Show resolved Hide resolved
src/object.cr Outdated
# identical environment) is an ideal representation. It doesn't need to be
# actual code that compiles, but a resemblance is recommended.
# When this is not possible (for example for non-printable internal state)
# another useful description will do.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also not entirely happy with this wording, but it's more of style than anything else. Perhaps we can pick a couple of (good) examples from the stdlib instead?

src/object.cr Outdated
# Similar to `to_s(io)`, but usually appends more information
# about this object.
# See `#inspect`.
# `::p` and `::p!` use this method to present an object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to have the :: here? doc doesn't resolve it correctly? More a curiosity than a request to change.

Suggested change
# `::p` and `::p!` use this method to present an object.
# `p` and `p!` use this method to present an object.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah otherwise the docs generator wouldn't catch the reference to p.

#
# The result resembles an array literal but it does not necessarily compile.
#
# Each element is presented using its `#inspect(io)` result to avoid ambiguity.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention avoiding circular references here? Or perhaps some other wording that explains the ...? The docs also serve for people writing overrides and I think catching circular references is important for those overriders to know about.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we only have to revisit this if/when we consider making exec_recursive a public API

Co-authored-by: Beta Ziliani <beta@manas.tech>
@straight-shoota straight-shoota self-assigned this Dec 8, 2022
Copy link
Member

@beta-ziliani beta-ziliani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment for inspect was still a bit odd for me. I rewrote it. WDYT?

src/object.cr Outdated
# identical environment) is an ideal representation. It doesn't need to be
# actual code that compiles, but a resemblance is recommended.
# When this is not possible (for example for non-printable internal state)
# another useful description will do.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't add a suggestion to the entire block, so here it goes in plain 🤷

  # Prints to *io* an unambiguous and information-rich string representation of this
  # object, typically intended for developers.
  #
  # It is similar to `#to_s(IO)`, but often provides more information. Ideally, it should
  # contain sufficient information to be able to recreate an object with the same value
  # (given an identical environment).
  #
  # For types that don't provide a custom implementation of this method,
  # default implementation delegates to `#to_s(IO)`. This said, it is advisable to 
  # have an appropriate `#inspect` implementation on every type. Default
  # implementations are provided by `Struct#inspect` and `Reference#inspect`.
  #
  # `::p` and `::p!` use this method to print an object in `STDOUT`.

@beta-ziliani beta-ziliani added this to the 1.7.0 milestone Dec 14, 2022
@straight-shoota straight-shoota merged commit dab949e into crystal-lang:master Dec 15, 2022
@straight-shoota straight-shoota deleted the docs/to_s-inspect branch December 15, 2022 12:25
carlhoerberg pushed a commit to carlhoerberg/crystal that referenced this pull request Dec 21, 2022
…9974)

Co-authored-by: Beta Ziliani <beta@manas.tech>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RFC] Specify #to_s vs #inspect
8 participants