[ruby-core:115071] [Ruby master Misc#19931] to_int is not for implicit conversion?

Issue #19931 has been reported by Dan0042 (Daniel DeLorme). ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by byroot (Jean Boussier). I may be wrong, but my understanding of it is that it's so the right hand side isn't always casted to the left-hand side type. If `to_int` was invoked when doing `Integer + something`, then `1 + 1.5` would be `1 + (1.5).to_int` and would return `2` instead of `2.5`. Hence why numerics use `coerce` instead. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104946 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by sawa (Tsuyoshi Sawada). Your description suggests a contrast between `to_int` and `to_i`, but while you showed a code example using `to_int`, you have not shown anything using `to_i`. Furthermore, actually replacing `to_int` in your code with `to_i` does not seem to make any difference. Your point is entirely not clear. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104948 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by nobu (Nobuyoshi Nakada). The order of such calculations is now: 1. known classes (e.g., `Integer#+` knows about `Float`) 2. `coerce` on the RHS. Otherwise raise an error. Might consider adding another step there. 3. try the implicit conversion. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104950 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by matheusrich (Matheus Richard).
3. try the implicit conversion.
If I understood this correctly, that would allow doing things like ```ruby 1 + "1" # => 2 ``` I hope that's not a direction we wanna follow. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104957 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by Dan0042 (Daniel DeLorme). sawa (Tsuyoshi Sawada) wrote in #note-2:
Your description suggests a contrast between `to_int` and `to_i`, but while you showed a code example using `to_int`, you have not shown anything using `to_i`.
If using `to_i` for explicit conversion, the example would be `def o.to_i; 1; end; 1 + o.to_i #=> 2` nobu (Nobuyoshi Nakada) wrote in #note-3:
Might consider adding another step there. 3. try the implicit conversion.
Yes, that's what I was talking about, and why it could work even for `1 + 1.5`. Any idea why this isn't done currently? Is it just that no one thought of it? matheusrich (Matheus Richard) wrote in #note-4:
If I understood this correctly, that would allow doing things like ```ruby 1 + "1" # => 2 ```
No, because "1" doesn't respond to `#to_int` ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104960 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by byroot (Jean Boussier). To be fair, `+` does it for `to_str`: ```ruby class Bar def to_str "bar" end end p "foo" + Bar.new # => "foobar" ``` So it would seem logical it would do the same for integers as well. I have no idea how much code it would break though. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104961 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by Eregon (Benoit Daloze). I think the coercion semantics are already quite complex, so we would need a convincing real-world use-case to make this more complicated. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104962 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by Dan0042 (Daniel DeLorme). byroot (Jean Boussier) wrote in #note-6:
I have no idea how much code it would break though.
It can't *break* code. It can only cause broken code (as in my example) to suddenly work. Eregon (Benoit Daloze) wrote in #note-7:
I think the coercion semantics are already quite complex, so we would need a convincing real-world use-case to make this more complicated.
I think it would make things simpler. For `1 + obj` you'd only have to define #to_int instead of the much more complex #coerce. And it would smooth out the hard-to-explain discrepancy that to_str/to_ary/to_hash allow implicit conversion but somehow to_int doesn't. But that's only if the current behavior of to_int wasn't deliberate. And if it was I'd just like to know the rationale. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104997 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by zverok (Victor Shepelev).
So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case?
As far as I understand, it is exactly the case for operations that definitely expect an integer: ```ruby o = Object.new def o.to_int = 5 ('a'..'z').to_a[o] #=> "f" ('a'..'z').first(o) # => ["a", "b", "c", "d", "e"] 'a' * o # => "aaaaa" ``` (All of those cases would also clearly state "no **implicit** conversion of Object into Integer" if the argument wouldn't have `#to_int`.) ...while number arithmetics seems to be fully defined by `#coerce` and never tries to perform "implicit conversions". ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-104998 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by Dan0042 (Daniel DeLorme). Aha! Thank you, now it makes a lot more sense. While I still think that `1 + o` would be nice to have, at least I can see the rhyme and reason. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-105004 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by matz (Yukihiro Matsumoto). I agree with the idea of adding `to_int` to implicit type conversion as @nobu stated in #note-3. Let's experiment. Matz. ---------------------------------------- Misc #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-105359 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by mame (Yusuke Endoh). @matz Nobu found `0 ^ 1.1 #=> 1` by this change. Is it ok? ---------------------------------------- Feature #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-105426 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by Dan0042 (Daniel DeLorme). A few weeks ago I experimented and tried to polyfill this via Object#coerce, and it doesn't result in `0 ^ 1.1 == 1` ```ruby class Object def coerce(other) if self.respond_to?(:to_int) to_int.coerce(other) else raise TypeError, "#{self.class} can't be coerced into #{other.class}" end end end x = Object.new def x.to_int = 5 1 + x #=> 6 0 ^ 1.1 #1.1 can't be coerced into Integer (TypeError) ``` ---------------------------------------- Feature #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-105454 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by Eregon (Benoit Daloze). I think it would be a mistake to try `to_int` for arithmetic operators. Why not try to_f, to_r, etc then? (or their implicit conversion variants, although they don't currently exist) It might accidentally round values which seems pretty bad. That's the point of `coerce`, it actually finds a meaningful numeric type for the result. ---------------------------------------- Feature #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-105466 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/

Issue #19931 has been updated by Dan0042 (Daniel DeLorme).
Why not try to_f, to_r, etc then? (or their implicit conversion variants, although they don't currently exist)
Because they're for explicit conversion. That would be like implicitly calling #to_i, and that's obviously a bad idea. ---------------------------------------- Feature #19931: to_int is not for implicit conversion? https://bugs.ruby-lang.org/issues/19931#change-105467 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal ---------------------------------------- While reviewing some implicit vs explicit conversion concepts, I discovered that arithmetic operations do not perform the implicit conversion I expected from #to_int ```ruby o = Object.new def o.to_int; 1; end 1 + o #TypeError ``` I understand there's the whole #coerce thing for numbers, but I had expected #to_int to fit neatly into this and cause the object to be implicitly coerced to Integer. So basically I thought that #to_i was for explicit conversion and #to_int for implicit conversion; is that not the case? Most of the internet seems to think that (to_int : to_i) relationship is like (to_str : to_s). But I can't seems to find authoritative documentation on the topic. -- https://bugs.ruby-lang.org/
participants (9)
-
byroot (Jean Boussier)
-
Dan0042 (Daniel DeLorme)
-
Eregon (Benoit Daloze)
-
mame (Yusuke Endoh)
-
matheusrich (Matheus Richard)
-
matz (Yukihiro Matsumoto)
-
nobu (Nobuyoshi Nakada)
-
sawa (Tsuyoshi Sawada)
-
zverok (Victor Shepelev)