TryStrToInt declaration question lazarus / 62-General ---------------------------------------------------------------------- lagprogramming · 2022-01-17 16:31 Hi! Regarding the "TryStrTo..." functions, we have a single function name to convert strings to single, double or extended, it's TryStrToFloat. Not all CPUs support extended, double, some not even single. Why do we have TryStrToInt for 32bit variables, TryStrToInt64 for 64bit signed variables and TryStrToQWord for 64bit unsigned variables? I found this situation when I realized that calling TryStrToInt with a sizeuint parameter may lead to errors when I target x86_64. I've looked at rtl documentation and I've seen: Declaration: function TryStrToInt(const s: string; out i: LongInt) : Boolean Declaration: function TryStrToInt64(const s: string; out i: Int64) : Boolean Declaration: function TryStrToQWord(const s: string; out Q: QWord) : Boolean How comes that for 32bit we have a single function(TryStrToInt) with a longint parameter, but for 64bit we have a function for signed integers(TryStrToInt64) and a different function for unsigned integers(TryStrToQWord)? Thank you! ---------------------------------------------------------------------- ASerge · 2022-01-17 19:02 For historical reasons. The Int64 type was first introduced in Delphi4. And at the same time, the StrToInt64 function was added in addition to the existing StrToInt. Since overlapping functions (introduce in Delphi4 also) do not differ in the type of results, the names were chosen of course different. It is also worth noting that for 32-bit Intel processors, 32-bit integers and 10-bit floating-point numbers (extended) were native. Therefore, the functions StrToInt: Integer and StrToFloat:Extended were native, but StrToInt64: Int64 is optional. In later versions Delphi, TryStrTo... functions were added. With the preservation of names, of course. The StrToQWord function was added in FPC because the QWord type did not fit into Int64. A similar StrToUInt64 function was also added, but later, in Delphi. ---------------------------------------------------------------------- ASerge · 2022-01-17 19:12 Of course, if you don't like a lot of names, you can overload the functions: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$MODE OBJFPC}{$LONGSTRINGS ON} uses SysUtils; function TryStrToInt(const S: string; out Value: Int64): Boolean; inline; overload;begin  Result := SysUtils.TryStrToInt64(S, Value);end; function TryStrToInt(const S: string; out Value: QWord): Boolean; inline; overload;begin  Result := SysUtils.TryStrToQWord(S, Value);end; var  I32: Int32;  I64: Int64;  Q: QWord;begin  TryStrToInt('1', I32); // Call SysUtils.TryStrToInt  TryStrToInt('1', I64); // Call SysUtils.TryStrToInt64  TryStrToInt('1', Q); // Call SysUtils.TryStrToQWordend. ---------------------------------------------------------------------- lagprogramming · 2022-01-18 12:30 Let's assume that a developer has a code like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function foo(StringVariable:string; var Number:integer):boolean;var  IntegerVariable: integer;begin  {Pascal code}  if TryStrToInt(StringVariable,IntegerVariable) then...  {Additional pascal code}  Number:=IntegerVariable;end;    In order to make the above code work nicely and native with 64bit CPUs it's not enough to change the integer types to sizeint.    According to the slogan "Write once, compile anywhere", if the code in written in a 32bit environment(which means sizeint would have the same size as integer) each and every developer has to realize that TryStrToInt won't work as they expect when the code is compiled in a 64bit environment. Those developers needs some luck to realize that. If the developers realize that their code has a problem in using this function, they must come with a workaround. One workaround is the one presented by ASerge, other approaches might be using conditional compilation syntax like {$IF....} or using the Val routine directly. The approach involving workarounds is far from being crosscompile friendly.    Wouldn't be better to avoid pushing each and every developer to write workarounds in their code by making TryStrToInt also accept 64bit integers and then modify existing code in TryStrToInt64 and TryStrToQWord to make it call TryStrToInt? With this approach we would have a clean way of using TryStrToInt routine similar to TryStrToFloat while keeping existing written pascal code compatible, for historical reasons. ---------------------------------------------------------------------- Seenkao · 2022-01-18 12:49 разработчикам в любом случае надо будет приводить тип данных к компилируемой архитектуре. Понятно дело, это не надо будет делать пользователю. Но вот подгонка типов данных под компилируемую архитектуру... этот не очень благодарное дело. google translate: developers in any case will need to cast the data type to the compiled architecture. Clearly, the user does not need to do this. But here's the adjustment of data types to the compiled architecture ... this is not a very rewarding job. ---------------------------------------------------------------------- Zoran · 2022-01-18 13:50 I agree that you have a point. Only I think that, instead of unifying all to TryStrToInt overloads (could it create some (backwards-/Delphi-) compatibility problems?), perhaps the cleaner solution would be adding a new function TryStrToPtrInt to Sysutils. Anyway, it's worth making a feature request in bug tracker; do it. Then further discussion should go there. FPC developers will then decide which approach to take, if any. And using val directly is not really a big problem. ---------------------------------------------------------------------- Thaddy · 2022-01-18 14:06 Note that AFAIK the tryXXX family in trunk has been recently mutilated by the use of exceptions in its implementations. Just counter- intuitive to why those were designed and not Delphi compatible. This is currently only an issue for trunk. That is not "implementation detail", it misses the point of tryxxx.  : Don't rely on exceptions when not needed. As far as I can see, that is an introduction of dirty code in the RTL. I hope one see's its ways.... ---------------------------------------------------------------------- Zoran · 2022-01-18 14:25 Quote from: Thaddy on January 18, 2022, 03:06:40 pmit misses the point of tryxxx.  : Don't rely on exceptions when not needed. Of course. StrToInt should call TryStrToInt and only then raise if needed. Not the other way around, first unnecessary raise then catch and discard it. It's ridiculous. ---------------------------------------------------------------------- Thaddy · 2022-01-18 14:55 I saw the Delphi Implementation, so can not provide an uninformed  - un-biased - patch. I hope it has not made it into a release version. But it defeats the point. (btw: original Implementation was correct.) ---------------------------------------------------------------------- Bart · 2022-01-18 17:23 Quote from: Zoran on January 18, 2022, 03:25:30 pmQuote from: Thaddy on January 18, 2022, 03:06:40 pmit misses the point of tryxxx.  : Don't rely on exceptions when not needed. Of course. StrToInt should call TryStrToInt and only then raise if needed. Not the other way around, first unnecessary raise then catch and discard it. It's ridiculous. Both in 3.2.2 and in trunk the TryStrToXXX versions just call Val() and in trunk StrToxxx calls TryStrToXXX,whereas in 3.2.2 they call Val(). So, the TryStrToXXX functions do not call StrToXXX and then catch the exception. Bart ---------------------------------------------------------------------- MarkMLl · 2022-01-18 21:48 Quote from: Thaddy on January 18, 2022, 03:06:40 pmThat is not "implementation detail", it misses the point of tryxxx.  : Don't rely on exceptions when not needed. As far as I can see, that is an introduction of dirty code in the RTL. That's particularly unfortunate, since a few weeks ago somebody- neither a newcomer to the forum nor to the language- was criticising the entire library stack due to over-use of exceptions. How on earth did it get past review? The World wonders... MarkMLl ---------------------------------------------------------------------- Bart · 2022-01-18 21:59 OK, so which TryStrToXXX functions in trunk have been "mutilated" to use exceptions? AFAICS none of the TryStrToInt variants. Bart ---------------------------------------------------------------------- PascalDragon · 2022-01-19 09:31 Quote from: Thaddy on January 18, 2022, 03:06:40 pmNote that AFAIK the tryXXX family in trunk has been recently mutilated by the use of exceptions in its implementations. Just counter-intuitive to why those were designed and not Delphi compatible. This is currently only an issue for trunk. There is no issue, cause the Try… functions don't use exceptions. Quote from: MarkMLl on January 18, 2022, 10:48:00 pmQuote from: Thaddy on January 18, 2022, 03:06:40 pmThat is not "implementation detail", it misses the point of tryxxx.  : Don't rely on exceptions when not needed. As far as I can see, that is an introduction of dirty code in the RTL. That's particularly unfortunate, since a few weeks ago somebody- neither a newcomer to the forum nor to the language- was criticising the entire library stack due to over-use of exceptions. How on earth did it get past review? The World wonders... Nothing did get past review here, cause nothing like Thaddy mentioned happened. ---------------------------------------------------------------------- MarkMLl · 2022-01-19 10:00 Quote from: PascalDragon on January 19, 2022, 10:31:39 amNothing did get past review here, cause nothing like Thaddy mentioned happened. @Thaddy, would you like to explain what you think you've seen? MarkMLl ---------------------------------------------------------------------- lagprogramming · 2022-01-19 10:26 I've looked in the rtl documentation I have and I've seen the following declarations: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function IntToStr(Value: LongInt) : stringfunction IntToStr(Value: Int64) : stringfunction IntToStr(Value: QWord) : stringfunction UIntToStr(Value: QWord) : stringfunction UIntToStr(Value: Cardinal) : string   Maybe function IntToStr(Value: QWord) : string does the same thing as function UIntToStr(Value: QWord) : string, I don't know.    In addition to the fact that we have TryStrToFloat working with single, double and extended, the point presenting the above extras is that we have IntToStr functions working with 64bit integers, but we don't have TryStrToInt working with 64bit integers. This can't be good. There is no reason or hint to realize that contrary to the use of TryStrToFloat and IntToStr, a developer must use different function names when he wants to do what he expects from a TryStrToInt function. ---------------------------------------------------------------------- PascalDragon · 2022-01-19 13:01 Quote from: lagprogramming on January 19, 2022, 11:26:25 am   I've looked in the rtl documentation I have and I've seen the following declarations: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function IntToStr(Value: LongInt) : stringfunction IntToStr(Value: Int64) : stringfunction IntToStr(Value: QWord) : stringfunction UIntToStr(Value: QWord) : stringfunction UIntToStr(Value: Cardinal) : string   Maybe function IntToStr(Value: QWord) : string does the same thing as function UIntToStr(Value: QWord) : string, I don't know. The UIntToStr overloads were added for Delphi compatibility. Quote from: lagprogramming on January 19, 2022, 11:26:25 am   In addition to the fact that we have TryStrToFloat working with single, double and extended, the point presenting the above extras is that we have IntToStr functions working with 64bit integers, but we don't have TryStrToInt working with 64bit integers. This can't be good. There is no reason or hint to realize that contrary to the use of TryStrToFloat and IntToStr, a developer must use different function names when he wants to do what he expects from a TryStrToInt function. You can just as well use the following, then you don't need to deal with the differences between TryStrToInt and TryStrToInt64: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode objfpc}{$H+} uses  SysUtils; var  s: SizeInt;begin  if SizeInt.TryParse('8481849', s) then    Writeln(s)  else    Writeln('Invalid number');end. ---------------------------------------------------------------------- lagprogramming · 2022-01-19 14:22 Funny stuff. I've decided to write a new TryToWhateverInteger function and to my surprise I've found that almost 10 years ago I've written a TryToLongword function. This means that almost a decade a ago I've hit the same problem the only difference being that at that time the problem I've had was with 32bit unsigned integers and now with 64bit integers.  History repeating. ---------------------------------------------------------------------- Bart · 2022-01-19 14:51 The problem being? Bart ---------------------------------------------------------------------- lagprogramming · 2022-01-19 16:15 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function ErrorCompilingThis(const StringParam:string; out LongwordParam:longword):boolean;begin//Error at the following line: Call by var for arg no. 2 has to match exactly: Got "LongWord" expected "LongInt"result:=TryStrToInt(StringParam,LongwordParam);end; procedure TForm1.Button1Click(Sender: TObject);var  LW1,LW2:LongWord;beginLW1:=LongWord(not(0));LW2:=0;//Obviously, same error in the following lineif TryStrToInt(IntToStr(LW1),LW2) THEN   if LW1=LW2 then Form1.Caption:='OK';end;    Now I see there is a TryStrToDWord function, probably it existed even at the time I've written my own TryStrToLongword. Totally counter-intuitive names in the rtl, really.    Nowadays we have a generic function name TryStrToInt that supports multiple types of strings but when it comes to the integer parameter we're stuck with the longint one. In addition to this function name we have a dozen other functions but with precise names that do the same kind of thing as TryStrToInt and that support the same multiple types of strings but only one type of integer: TryStrToInt64, TryStrToQWord, TryStrToUInt64, TryStrToDWord and who knows how many others. If the function name has to identify the second parameter then TryStrToInt doesn't identify the LongInt parameter, it confuzes people into thinking that it's a function that applies to all sorts of integers like it applies to all sorts of strings.    I've given the TryStrToFloat example, here is another one:    TryStrToBool(const S: string; out Value: Boolean) : Boolean;    TryStrToBool(const S: string; out Value: Boolean; const FormatSettings: TFormatSettings) : Boolean;    The rtl doesn't have a TryStrToBool(const S: string; out Value: BYTEBOOL) : Boolean; declaration, neither a TryStrToLONGBOOL(const S: string; out Value: LONGBOOL) : Boolean declaration.    Probably due to historical reasons we have a function with a generic name that should cover many types of strings and integers, but it doesn't. At least I've been mislead by the name. ---------------------------------------------------------------------- ASBzone · 2022-02-08 22:05 Quote from: lagprogramming on January 17, 2022, 05:31:43 pmRegarding the "TryStrTo..." functions, we have a single function name to convert strings to single, double or extended, it's TryStrToFloat. Thank you! I had an application that needed several numeric conversions, and at first I just used TryStrToFloat, and typecast to the appropriate integer type when necessary. Yeah...  That was noticeably slower than staying within the fun realm of integers for integer results. ---------------------------------------------------------------------- ASBzone · 2022-02-08 22:19 Quote from: lagprogramming on January 19, 2022, 05:15:52 pmIn addition to this function name we have a dozen other functions but with precise names that do the same kind of thing as TryStrToInt and that support the same multiple types of strings but only one type of integer: TryStrToInt64, TryStrToQWord, TryStrToUInt64, TryStrToDWord and who knows how many others. It seems straightforward to me why you can have a single name for a myriad of functions when converting from IntegerX to String.  You're only looking for a single output type, and the parameter is going to be matched within the overloaded functions, so only one name is needed. However, if you are going to turn a single string into *some* type of Integer, how will the computer know what kind of Integer you wanted to end up with?  You might have specific reasons for asking for Int32 even if using a QWord variable.   How could this ever be easily communicated without a specific function name?