www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Question about: ("1.1").to!int;

reply matheus <matheus gmail.com> writes:
Hi,

import std.stdio, std.conv;
void main(string[ ] args) {
     auto a = (1).to!int;     // this works
     auto b = ("1").to!int;   // this works
     auto c = (1.1).to!int;   // this works and c = 1
     auto d = ("1.1").to!int; // Doesn't work
}

The forth line gives me:

std.conv.ConvException /usr/include/dlang/dmd/std/conv.d(1898): 
Unexpected '.' when converting from type string to type int
----------------
??:? pure  safe int std.conv.toImpl!(int, 
immutable(char)[]).toImpl(immutable(char)[]) [0x55de76d9b4d7]
??:? pure  safe int 
std.conv.to!(int).to!(immutable(char)[]).to(immutable(char)[]) 
[0x55de76d99a17]
??:? _Dmain [0x55de76d9986e]

Question:

Since (1.1).to!int = 1, shouldn't the string value ("1.1").to!int 
at least try to convert to float/double and then to int?

Because for what I see "to!int" converts from: int,real but in 
case of string only when it is a integer representation?

Matheus.
Oct 21 2020
next sibling parent bachmeier <no spam.net> writes:
On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:

 Since (1.1).to!int = 1, shouldn't the string value 
 ("1.1").to!int at least try to convert to float/double and then 
 to int?
I don't think so. A silent string->double conversion isn't IMO consistent with D's design. "1.1".to!double.to!int works fine, and I like that you have to be explicit, because there is so much room for error. Note that "1".to!double.to!int works as expected. Therefore you should be able to use that all the time.
Oct 21 2020
prev sibling next sibling parent reply =?UTF-8?B?0JLQuNGC0LDQu9C40Lkg0KTQsNC0?= =?UTF-8?B?0LXQtdCy?= writes:
On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
 Hi,

 import std.stdio, std.conv;
 void main(string[ ] args) {
     auto a = (1).to!int;     // this works
     auto b = ("1").to!int;   // this works
     auto c = (1.1).to!int;   // this works and c = 1
     auto d = ("1.1").to!int; // Doesn't work
 }

 [...]
1.1 is not int. "to" works fine. As solution,... "1.1" should be splitted to lexems: "1", ".", "1". Then analyze and then converted to int.
Oct 23 2020
parent matheus <matheus gmail.com> writes:
On Friday, 23 October 2020 at 08:09:13 UTC, Виталий Фадеев wrote:
 On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
 Hi,

 import std.stdio, std.conv;
 void main(string[ ] args) {
     auto a = (1).to!int;     // this works
     auto b = ("1").to!int;   // this works
     auto c = (1.1).to!int;   // this works and c = 1
     auto d = ("1.1").to!int; // Doesn't work
 }

 [...]
1.1 is not int. "to" works fine. As solution,... "1.1" should be splitted to lexems: "1", ".", "1". Then analyze and then converted to int.
Of course 1.1 it's not an integer, but since (1.1).to!int works I thought that ("1.1").to!int should work too. Matheus.
Oct 23 2020
prev sibling next sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
 Since (1.1).to!int = 1, shouldn't the string value 
 ("1.1").to!int at least try to convert to float/double and then 
 to int?
The thing is, that's a great way for hard-to-identify bugs to creep into code. In these cases: auto a = (1).to!int; // this works auto b = ("1").to!int; // this works auto c = (1.1).to!int; // this works and c = 1 ... then what the programmer wants is unambiguous. In the first case it's just converting int => int. In the second, it's converting from a string that unambiguously represents an integer value, to an int. And in the third, it's converting _at programmer request_ from a double to an int (which has a well-defined behaviour). However, if ("1.1").to!int were to work, this would be the `to` function making a judgement call on how to handle something ambiguous. And while that judgement call may be acceptable for your current use-case, it won't be for others. In particular, if `to` just accepted any string numerical representation for conversion to int, how could the caller explicitly _exclude_ non-integer input, if that is their use-case? So it's far better to require you, as the programmer, to make what you want unambiguous and explicitly write code that will (i) deserialize any numerical string that is acceptable to you and (ii) convert to integer.
Oct 23 2020
next sibling parent reply user1234 <user1234 12.de> writes:
On Friday, 23 October 2020 at 13:57:41 UTC, Joseph Rushton 
Wakeling wrote:
 On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
 Since (1.1).to!int = 1, shouldn't the string value 
 ("1.1").to!int at least try to convert to float/double and 
 then to int?
The thing is, that's a great way for hard-to-identify bugs to creep into code. In these cases: auto a = (1).to!int; // this works auto b = ("1").to!int; // this works auto c = (1.1).to!int; // this works and c = 1 ... then what the programmer wants is unambiguous. In the first case it's just converting int => int. In the second, it's converting from a string that unambiguously represents an integer value, to an int. And in the third, it's converting _at programmer request_ from a double to an int (which has a well-defined behaviour). However, if ("1.1").to!int were to work, this would be the `to` function making a judgement call on how to handle something ambiguous. And while that judgement call may be acceptable for your current use-case, it won't be for others. In particular, if `to` just accepted any string numerical representation for conversion to int, how could the caller explicitly _exclude_ non-integer input, if that is their use-case? So it's far better to require you, as the programmer, to make what you want unambiguous and explicitly write code that will (i) deserialize any numerical string that is acceptable to you and (ii) convert to integer.
The third case is just like `cast(int) 1.1` it's not _at programmer request_ from my point of view, it's just that the `to` template has not be more restrictive than the D `cast` expression. `to` should do at least what a `cast` do and do more when there's no rule for the two types that are involved.
Oct 23 2020
parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On Friday, 23 October 2020 at 14:16:50 UTC, user1234 wrote:
 The third case is just like `cast(int) 1.1` it's not _at 
 programmer request_ from my point of view
If the programmer explicitly writes a `to!int` or the `cast(int)`, then it's pretty clearly at their request. And it's unambiguous what they are asking for. But if the input to the conversion is a string, it's important that the conversion fail unless the string is an unambiguous representation of the intended destination type. Otherwise, there is more than one data conversion going on, and one of them is being hidden from the programmer.
Oct 23 2020
prev sibling next sibling parent bachmeier <no spam.net> writes:
On Friday, 23 October 2020 at 13:57:41 UTC, Joseph Rushton 
Wakeling wrote:

 In particular, if `to` just accepted any string numerical 
 representation for conversion to int, how could the caller 
 explicitly _exclude_ non-integer input, if that is their 
 use-case?

 So it's far better to require you, as the programmer, to make 
 what you want unambiguous and explicitly write code that will 
 (i) deserialize any numerical string that is acceptable to you 
 and (ii) convert to integer.
Yes, that's the problem, and it doesn't make sense to use a statically typed language if the standard library silently introduces holes that lead to serious bugs (in this case, loss of numerical precision, which can be pretty nasty). The solution is simple in this case, and it even leads to one less character when you're writing your program: import std; void main() { int toInt(string s) { return(s.to!double.to!int); } writeln(toInt("1")); writeln(toInt("1.1")); writeln(toInt("a")); }
Oct 23 2020
prev sibling parent reply matheus <matheus gmail.com> writes:
On Friday, 23 October 2020 at 13:57:41 UTC, Joseph Rushton 
Wakeling wrote:
 On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
 Since (1.1).to!int = 1, shouldn't the string value 
 ("1.1").to!int at least try to convert to float/double and 
 then to int?
The thing is, that's a great way for hard-to-identify bugs to creep into code. In these cases: auto a = (1).to!int; // this works auto b = ("1").to!int; // this works auto c = (1.1).to!int; // this works and c = 1 ... then what the programmer wants is unambiguous. In the first case it's just converting int => int. In the second, it's converting from a string that unambiguously represents an integer value, to an int. And in the third, it's converting _at programmer request_ from a double to an int (which has a well-defined behaviour). However, if ("1.1").to!int were to work, this would be the `to` function making a judgement call on how to handle something ambiguous. And while that judgement call may be acceptable for your current use-case, it won't be for others.
I got it everything you said, but like a said previously: (1.1).to!int vs ("1.1").to!int One is a decimal literal while the other is a string representation of a decimal. To be honest I think the function is already making a judgment call when I do (1.1).to!int and returns 1, I really fail to see the difference when is ("1.1").to!int. I agree with user1234: "The third case is just like `cast(int) 1.1` it's not _at programmer request_ from my point of view, it's just that the `to` template has not be more restrictive than the D `cast` expression. `to` should do at least what a `cast` do and do more when there's no rule for the two types that are involved."
 In particular, if `to` just accepted any string numerical 
 representation for conversion to int, how could the caller 
 explicitly _exclude_ non-integer input, if that is their 
 use-case?
Well since the caller is handling a string, shouldn't the caller verify the content before any conversion? Because a string may contain a integer, decimal representation or neither one. Finally I don't want to make a fuss of it, I just thought it was a bit weird but it can be solved easily. Thanks, Matheus.
Oct 23 2020
next sibling parent =?UTF-8?B?0JLQuNGC0LDQu9C40Lkg0KTQsNC0?= =?UTF-8?B?0LXQtdCy?= writes:
On Friday, 23 October 2020 at 16:59:06 UTC, matheus wrote:
 On Friday, 23 October 2020 at 13:57:41 UTC, Joseph Rushton 
 Wakeling wrote:
 On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
 Since (1.1).to!int = 1, shouldn't the string value 
 ("1.1").to!int at least try to convert to float/double and 
 then to int?
The thing is, that's a great way for hard-to-identify bugs to creep into code. In these cases: auto a = (1).to!int; // this works auto b = ("1").to!int; // this works auto c = (1.1).to!int; // this works and c = 1 ... then what the programmer wants is unambiguous. In the first case it's just converting int => int. In the second, it's converting from a string that unambiguously represents an integer value, to an int. And in the third, it's converting _at programmer request_ from a double to an int (which has a well-defined behaviour). However, if ("1.1").to!int were to work, this would be the `to` function making a judgement call on how to handle something ambiguous. And while that judgement call may be acceptable for your current use-case, it won't be for others.
I got it everything you said, but like a said previously: (1.1).to!int vs ("1.1").to!int One is a decimal literal while the other is a string representation of a decimal. To be honest I think the function is already making a judgment call when I do (1.1).to!int and returns 1, I really fail to see the difference when is ("1.1").to!int. I agree with user1234: "The third case is just like `cast(int) 1.1` it's not _at programmer request_ from my point of view, it's just that the `to` template has not be more restrictive than the D `cast` expression. `to` should do at least what a `cast` do and do more when there's no rule for the two types that are involved."
 In particular, if `to` just accepted any string numerical 
 representation for conversion to int, how could the caller 
 explicitly _exclude_ non-integer input, if that is their 
 use-case?
Well since the caller is handling a string, shouldn't the caller verify the content before any conversion? Because a string may contain a integer, decimal representation or neither one. Finally I don't want to make a fuss of it, I just thought it was a bit weird but it can be solved easily. Thanks, Matheus.
For _execution speed_ reason we need low-level functions. What if on each call ("1").to!int we will do parsing "1" for decimal point "." ? . Should be Low-level functions and High-level functions. "to" is Low-level function. . You can create "To" function with parsing & validating. You right: if "to" generating exception for non-numeric symbol, then it doing test each char... and "to" can just break loop at non-numeric symbol. . And... . "1".to!int "1.1".to!int "1abc".to!int ...they all can be == 1 . Some like this: foreach( c; str ) if ( c.between( '0', '9' ) ) result *= factor; result += ( c-'0' ); else break; . You can write patch.
Oct 23 2020
prev sibling parent reply =?UTF-8?B?0JLQuNGC0LDQu9C40Lkg0KTQsNC0?= =?UTF-8?B?0LXQtdCy?= writes:
On Friday, 23 October 2020 at 16:59:06 UTC, matheus wrote:
 On Friday, 23 October 2020 at 13:57:41 UTC, Joseph Rushton 
 Wakeling wrote:
 On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
Well since the caller is handling a string, shouldn't the caller verify the content before any conversion?
What if: "1.1.1".to!int ? The algorithm will become more complicated? Will the speed decrease?
Oct 23 2020
parent reply matheus <matheus gmail.com> writes:
On Saturday, 24 October 2020 at 04:04:18 UTC, Виталий Фадеев 
wrote:
 On Friday, 23 October 2020 at 16:59:06 UTC, matheus wrote:
 On Friday, 23 October 2020 at 13:57:41 UTC, Joseph Rushton 
 Wakeling wrote:
 On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
Well since the caller is handling a string, shouldn't the caller verify the content before any conversion?
What if: "1.1.1".to!int ? The algorithm will become more complicated? Will the speed decrease?
I don't get... Anyway this should fail, look "1.1" is one thing, "1.1.1" is another thing as "1.a" is another thing. Like I said before I think the behavior should be the same in these cases: (1.1).to!int = 1. ("1.1").to!int = Current is an error and IMO should be 1. Now for your question: 1.1.1.to!int = Error: found `0.1` when expecting `,`. "1.1.1".to!int = Should be the same as above. Matheus.
Oct 24 2020
parent =?UTF-8?B?0JLQuNGC0LDQu9C40Lkg0KTQsNC0?= =?UTF-8?B?0LXQtdCy?= writes:
On Saturday, 24 October 2020 at 14:10:02 UTC, matheus wrote:
 On Saturday, 24 October 2020 at 04:04:18 UTC, Виталий Фадеев 
 wrote:
 On Friday, 23 October 2020 at 16:59:06 UTC, matheus wrote:
 On Friday, 23 October 2020 at 13:57:41 UTC, Joseph Rushton 
 Wakeling wrote:
 On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
I don't get... (1.1).to!int = 1. ("1.1").to!int = Current is an error and IMO should be 1. Matheus.
You should write converter from string to int. Then you will understand. You converter input: "1" "1.1" "1.1.1" "1a" "1.1a" "a" ".1" ".1.1" You converter must be fast.
Oct 24 2020
prev sibling parent Jack <jckj33 gmail.com> writes:
On Wednesday, 21 October 2020 at 22:50:27 UTC, matheus wrote:
 Hi,

 import std.stdio, std.conv;
 void main(string[ ] args) {
     auto a = (1).to!int;     // this works
     auto b = ("1").to!int;   // this works
     auto c = (1.1).to!int;   // this works and c = 1
     auto d = ("1.1").to!int; // Doesn't work
 }

 The forth line gives me:

 std.conv.ConvException /usr/include/dlang/dmd/std/conv.d(1898): 
 Unexpected '.' when converting from type string to type int
 ----------------
 ??:? pure  safe int std.conv.toImpl!(int, 
 immutable(char)[]).toImpl(immutable(char)[]) [0x55de76d9b4d7]
 ??:? pure  safe int 
 std.conv.to!(int).to!(immutable(char)[]).to(immutable(char)[]) 
 [0x55de76d99a17]
 ??:? _Dmain [0x55de76d9986e]

 Question:

 Since (1.1).to!int = 1, shouldn't the string value 
 ("1.1").to!int at least try to convert to float/double and then 
 to int?

 Because for what I see "to!int" converts from: int,real but in 
 case of string only when it is a integer representation?

 Matheus.
In first case you asked to convert a float (inferred by templace function) to int in the second case, you asked for the function "convert this string contaning a set of digits to an int for me". Doesn't make sense do something else than the asked. D has static if() and a nice way to do type comparasion at compile time. It does optimize things alot. I haven't read the to source code, but consider it may use the idea like this: auto to(T, T2)(T2 source) { // you asked for int, doesn't makes sense consider a float here. // that would waste time checking for floats when you programmer's requested // was clear: an integer. static if(is(T == int) && is(T2 == string)) { int v = 0; foreach(c; source) v = v * 10 + c - '0'; return v; } // the string to float point conversion algorithm static if(is(T == float) && is(T2 == string)) { /* ... */ } static if(is(T == int) && is(T2 == double)) { return cast(int)source; } assert(0, "unknow type"); }
Oct 24 2020