Crystal: [RFC] Remove suffixes of integers in inspect

Created on 15 Jun 2018  路  20Comments  路  Source: crystal-lang/crystal

It's so nice now that with Crystal 0.25.0 one can do:

a = [1, 2, 3] of Int64
a << 4
p a

However, the output is:

[1_i64, 2_i64, 3_i64, 4_i64]

That's unreadable. The numbers gets mixed with the 64 from the suffix. Imagine debugging some code related to math/numbers, it's very hard to read. The code already states that the integer is Int64. Why does it need to be explicitly stated in the output? It's just noise, and very annoying noise.

I propose we revert this change. Otherwise to print such code.

Note that even using puts a will print it this way, because Array#to_s uses inspect for each element (like in Ruby, so that's actually fine/good, specially if the Array has objects).

This is further a problem if such array is part of an object:

class Foo
  property a = [1, 2, 3] of Int64
end

p Foo.new

Output:

#<Foo:0x10e4a2f20 @a=[1_i64, 2_i64, 3_i64]>

So much noise...

Can we please revert this change? :-)

Thank you 鉂わ笍

Most helpful comment

@RX14 Could you and everyone else reconsider this? I'm currently trying to improve the performance of parsing dwarf debug info and I usually debug a lot using p, pp, etc. Dwarf uses UInt32 and UInt64 and other "non-Int32" types all over the places, and it's so tedious to constantly see the _u32 and _u64 suffixes all over the place, and when I dump info into a file to process it I have to remove those suffixes each and every time. It's really taking out all the fun of Crystal for me.

I'd really like to print numbers like every other language on Earth prints them.

All 20 comments

How about a middle choice here? Could the output for Array#inspect in this case instead be [1, 2, 3, 4] of Int64?

It would get ambiguous for union types though, I suppose, so perhaps it wouldn't be a good idea.

@yxhuvud It's not about arrays. You also can have:

class Foo
  property a : Int64 = 0
end

p Foo.new.a # => 0_i64

There's no need for a user to see _i64 in the output. I mean, if you ask "you have 1 and 2, both Int64, and you add them, what's the result?" the answer is of course "3", but it's a bit redundant to say "oh, and, by the way, it's an Int64", and see that "oh, by the way, all these numbers are Int64" every time you output something.

In Ruby there's Fixnum, Float, BigInt, BigDecimal, Complex, etc. You don't get to see "1_fix", "1_big", etc., in the output. As a developer I might care about the types, when I program, but not when I output stuff in the console, or send it to some log.

#inspect should always print the data type of a number. It's still a huge difference if a value is Int64 or UInt8, even if it typically doesn't matter for literals used in method arguments.

It's still a huge difference if a value is Int64 or UInt8, even if it typically doesn't matter for literals used in method arguments

Why, in the context of seeing the value in a console output?

If the value is of type Int64 | UInt8, I might very much be interested in the actual data type. That's what #inspect is for. If you don't need the data type, use to_s.

If the value is of that type, you have a code smell. And if not, what's use is it if it's one type or another, in the debug output?

Anyway, do what you want with this. No other language does it this way, not even languages with multiple types of integers.

Just wondering... how many languages have different integer types and inspect-like debug output in stdlib? Most that I can think of, have either one of these features (or none), but not both. Do you know of any example?

@straight-shoota Julia . It has all these integer types and it never uses a suffix when outputting stuff. I mean, imagine someone doing math or science and getting all thosei_64 in the output. Not very comfortable or useful.

We've had this discussion before and we didn't agree to a change back then.

Knowing the type of your numbers without explicitly printing typeof(var) or var.class is useful to people. Yes, having a union of different number types is a code smell, but when you're debugging you really want to know the most about your code so you can spot if you or someone else has accidentally written a code smell. I imagine with map {} and a ternary or if block, it wouldn't be too hard to make an Array(Int32 | Int16) if you mistook the types of either side of your branch.

I don't think it's unreadable either. It's easy to ignore the suffixes when looking at the output for me.

Of course I am biased, because I implemented this :P

We could think about a special case for array, though. If an array has only one type of integer, the output of inspect could actually call to_s on each member, as @yxhuvud suggested (https://github.com/crystal-lang/crystal/issues/6196#issuecomment-397645983), removing redundant type suffixes.

@RX14 Could you and everyone else reconsider this? I'm currently trying to improve the performance of parsing dwarf debug info and I usually debug a lot using p, pp, etc. Dwarf uses UInt32 and UInt64 and other "non-Int32" types all over the places, and it's so tedious to constantly see the _u32 and _u64 suffixes all over the place, and when I dump info into a file to process it I have to remove those suffixes each and every time. It's really taking out all the fun of Crystal for me.

I'd really like to print numbers like every other language on Earth prints them.

I couldn't agree more.

Coming to this after a long time. I'm quite shocked that we're still doing this :man_facepalming:

%100 agree with what @asterite said I'd really like to print numbers like every other language on Earth prints them.

@asterite Actually, only RX14's comment was a clear vote against this proposal and after that you simply closed the issue ;)

If we proceed with this, what would be the alternative for printing a number + it's type? Number#dump?

@straight-shoota p typeof(num). We could consider adding #dump, but I can't find a use case for showing a number like 123_u64.

You probably mean p num.class instead of p typeof(num), right? typeof won't show the actual number type if it could be different ones.

For reference, this is the PR that added this feature: #4747

A use case specifically for 123_u64 would be to print a number literal that could be used in Crystal code as is. It's probably not very important. But I'd like to have a way to inspect a number including its type that's less tedious than p num, num.class. That's where #dump would fit.

@straight-shoota Yes, p num.class is probably more correct. We can add #dump to Number.

Agree with @straight-shoota, we need to keep a way to view the 'real type' of the data and especially numbers, since the same printed number could me many types..

Instead of #dump I was thinking about #dbg or #debug or even #debug_print_with_types that would be called by a macro specially made to debug things with types and other info

BTW: There are also #6615 and #6616 both having some relevant comments. But having multiple discussion threads makes a real mess...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lbguilherme picture lbguilherme  路  3Comments

relonger picture relonger  路  3Comments

oprypin picture oprypin  路  3Comments

RX14 picture RX14  路  3Comments

lgphp picture lgphp  路  3Comments