[NO SOLUTION] Case with string in Delphi mode lazarus / 64-FPC development ---------------------------------------------------------------------- Okoba · 2021-09-04 08:14 I can not find any option or switch to activate this option in Delphi mode. Is there one or can be one? I am using some Delphi only options (like the lighter generic syntax) so I prefer to remain with the Delphi mode for now. 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 program Project1; {$MODE Delphi} var  V: String;begin  V := 'AAA';  case V of    'AAA': ;    'BBB': ;  end;end. ---------------------------------------------------------------------- Jonas Maebe · 2021-09-04 08:48 No, it cannot be enabled in Delphi mode (nor in TP or MacPas modes). ---------------------------------------------------------------------- Okoba · 2021-09-04 08:52 Pity. Thanks. ---------------------------------------------------------------------- wp · 2021-09-04 09:24 The {$MODE} directive is per unit. So, if you somehow can concentrate all your "case string of" stuff in a separate unit you can use {$MODE objfpc}{$H+} there and {$MODE Delphi} elsewhere. ---------------------------------------------------------------------- Okoba · 2021-09-04 10:28 Yes, but the problem of being in two modes keeps getting bigger and bigger. Not having 'operator' in Delphi mode, or keep forcing them to write generic/specialize everywhere. To be clear, I am not writing Delphi compatible code, but I like to have the lighter syntax of generics in the FPC mode, as in a heavy- generic code, generic/specialize makes everything seem more complicated than it really is. Also, in the coming of implicit generics, it would be much better to utilize generics in a light syntax. ---------------------------------------------------------------------- bytebites · 2021-09-05 17:47 It is quite artificial limitation. Find following code in the pstatmnt.pas file and do something to m_delphi-string. Then compile and install the compiler. 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          caseofstring :=           ([m_delphi, m_mac, m_tp7] * current_settings.modeswitches = []) and           is_string(casedef); ---------------------------------------------------------------------- Okoba · 2022-03-16 09:50 Any updates on this? Should I add a feature request on Gitlab? ---------------------------------------------------------------------- wp · 2022-03-16 10:01 In your code sample of the first post the strings had a length of only a single character. If this is true for your case in general then you could simple declare variable V as a char, and it should work in Delphi, too. ---------------------------------------------------------------------- Okoba · 2022-03-16 10:11 Yes it can be used but the sample was misunderstood. I updated it. For clarification I like to have the similar ability in objfpc mode for Delphi. ---------------------------------------------------------------------- wp · 2022-03-16 10:21 Quote from: Okoba on March 16, 2022, 10:50:22 amShould I add a feature request on Gitlab? You can try, but I am rather sure that it will be rejected. Mode Delphi is intended to provide the same language features that Delphi has. But since Delphi has no "case of string", FPC won't have it in mode Delphi, either. Make a feature request with Embarcadero instead... ---------------------------------------------------------------------- Okoba · 2022-03-16 10:23 Its been years that I used Delphi. I use Delphi mode only for the more clear/clean generic syntax. So I am stuck between features of objfpc and cleanness of delphi mode. ---------------------------------------------------------------------- PascalDragon · 2022-03-17 11:29 Quote from: Okoba on March 16, 2022, 10:50:22 amAny updates on this? Should I add a feature request on Gitlab? You already got a reply from Jonas Maebe who is a compiler dev and who said “No”. What more updates do you expect there? ---------------------------------------------------------------------- Okoba · 2022-03-17 11:44 Considering what @bytebites pointed out, maybe a switch? P.S. I did not know Jonas is a compiler dev. ---------------------------------------------------------------------- Thaddy · 2022-03-17 12:01 Case of string is not supported by Delphi, period. Most Delphi features are supported by FPC, but many features from fpc are not supported by Delphi. (BTW: this feature lead to heavily contested discussions: imho it should not be there) ---------------------------------------------------------------------- PascalDragon · 2022-03-17 12:08 Quote from: Okoba on March 17, 2022, 12:44:18 pmConsidering what @bytebites pointed out, maybe a switch? P.S. I did not know Jonas is a compiler dev. Jonas already said “No”. So, again, no. ---------------------------------------------------------------------- Okoba · 2022-03-17 12:23 Thanks. ---------------------------------------------------------------------- bytebites · 2022-03-17 12:45 There is solution: Modify your compiler. ---------------------------------------------------------------------- Okoba · 2022-03-17 12:49 Not a good way to maintain your own version of the compiler for just this simple change. Although these minor issues are piling up, string case, generics, and operators ObjFPC and Delphi mode each have their best features, and I wish we could have both. For now, the best solution is to have different units for different needs, not clean though. ---------------------------------------------------------------------- MarkMLl · 2022-03-17 12:53 Quote from: Okoba on March 17, 2022, 12:44:18 pmP.S. I did not know Jonas is a compiler dev. Of many years standing, and with significant academic etc. credentials. Noting Thaddy's comment that something like this should have no place in the language: I've got reservations, but it's undeniably useful when writing command parsers etc. By comparison, I've seen a language family that required this sort of thing to be done using predefined constant tables, and the separation of data and control resulted in a grievous loss of clarity. However, I'd be very interested if somebody (Sven?) had a suggestion of how the current case could be replaced by something more genuine: an inline table of paired literals and lambdas or similar. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2022-03-18 14:54 Quote from: MarkMLl on March 17, 2022, 01:53:38 pmNoting Thaddy's comment that something like this should have no place in the language: I've got reservations, but it's undeniably useful when writing command parsers etc. By comparison, I've seen a language family that required this sort of thing to be done using predefined constant tables, and the separation of data and control resulted in a grievous loss of clarity. To be fair, case of with a string expression is absolutely a syntatic sugar for a sequence of if-statements in contrast to the one for ordinals which offers a real performance difference. Quote from: MarkMLl on March 17, 2022, 01:53:38 pmHowever, I'd be very interested if somebody (Sven?) had a suggestion of how the current case could be replaced by something more genuine: an inline table of paired literals and lambdas or similar. What kind of improvement do you hope to get from something like this? ---------------------------------------------------------------------- MarkMLl · 2022-03-18 15:04 Quote from: PascalDragon on March 18, 2022, 03:54:11 pmWhat kind of improvement do you hope to get from something like this? I don't, frankly. But the more syntactic sugar that can be moved out of the language into support libraries the better IMO. I suppose though that a case statement- irrespective of the type of the controlling expression- is fairly closely related to the inline if-then-else that we've discussed before. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2022-03-18 15:09 Quote from: MarkMLl on March 18, 2022, 04:04:29 pmQuote from: PascalDragon on March 18, 2022, 03:54:11 pmWhat kind of improvement do you hope to get from something like this? I don't, frankly. But the more syntactic sugar that can be moved out of the language into support libraries the better IMO. You simply can't move things out of the language that are there already. The point is to be conservative to what is moved into the language instead. But with the upcoming anonymous functions or even with nested functions one could already create some generic case-like functionality. Quote from: MarkMLl on March 18, 2022, 04:04:29 pmI suppose though that a case statement- irrespective of the type of the controlling expression- is fairly closely related to the inline if-then-else that we've discussed before. Except for types where the compiler can at compile time determine an order (ordinals for example), cause then jump tables can be used (and the compiler does so for ordinals). ---------------------------------------------------------------------- Okoba · 2022-03-18 20:06 Quote from: PascalDragon on March 18, 2022, 04:09:07 pmBut with the upcoming anonymous functions or even with nested functions one could already create some generic case-like functionality. I'd like to see how one can do it with anonymous functions or nested functions as cleanly or almost as cleanly as case. ---------------------------------------------------------------------- MarkMLl · 2022-03-18 20:45 Quote from: PascalDragon on March 18, 2022, 04:09:07 pmYou simply can't move things out of the language that are there already. The point is to be conservative to what is moved into the language instead. But with an adequately-flexible base language one could some sort of general-purpose variadic syntax extension, and use that to reimplement case in a library. That's really no more outrageous than the idea of overloaded operators, which by my standards have come along fairly recently. QuoteBut with the upcoming anonymous functions or even with nested functions one could already create some generic case-like functionality. Yes, much what was anticipating. Can you put exit/continue/etc. in an anonymous function? MarkMLl ---------------------------------------------------------------------- Leledumbo · 2022-03-19 08:02 Quote from: PascalDragon on March 18, 2022, 03:54:11 pmTo be fair, case of with a string expression is absolutely a syntatic sugar for a sequence of if-statements in contrast to the one for ordinals which offers a real performance difference. Wish somebody can create a prefix tree based code generation for this, it will no longer be a simple syntactic sugar and will provide actual performance benefits, at least if the code is frequently executed. ---------------------------------------------------------------------- winni · 2022-03-19 10:10 Hi! This was my workaround in my Delphi times: 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 CaseOfString (s: string; CaseLabels : TStringArray) : Integer;var  i: Integer;beginresult := -1;for i := low (CaseLabels) to high(CaseLabels) do   begin   if s = CaseLabels[i] then      begin    result := i;      exit;      end;   end;end;  Winni ---------------------------------------------------------------------- PascalDragon · 2022-03-19 15:46 Quote from: Okoba on March 18, 2022, 09:06:45 pmQuote from: PascalDragon on March 18, 2022, 04:09:07 pmBut with the upcoming anonymous functions or even with nested functions one could already create some generic case-like functionality. I'd like to see how one can do it with anonymous functions or nested functions as cleanly or almost as cleanly as case. It will never be “as cleanly” or “almost as cleanly”. Essentially you need a function that maps your expression to an index and then an array of functions that contain the actions. Quote from: MarkMLl on March 18, 2022, 09:45:54 pmQuote from: PascalDragon on March 18, 2022, 04:09:07 pmYou simply can't move things out of the language that are there already. The point is to be conservative to what is moved into the language instead. But with an adequately-flexible base language one could some sort of general-purpose variadic syntax extension, and use that to reimplement case in a library. That's really no more outrageous than the idea of overloaded operators, which by my standards have come along fairly recently. FPC will definitely not go in this direction. Quote from: MarkMLl on March 18, 2022, 09:45:54 pmQuoteBut with the upcoming anonymous functions or even with nested functions one could already create some generic case-like functionality. Yes, much what was anticipating. Can you put exit/continue/etc. in an anonymous function? An anonymous function can not influence the code flow of the surrounding code, cause the anonymous function can be passed outside the surrounding code's scope. ---------------------------------------------------------------------- MarkMLl · 2022-03-19 16:42 Quote from: PascalDragon on March 19, 2022, 04:46:16 pmQuote from: MarkMLl on March 18, 2022, 09:45:54 pmBut with an adequately-flexible base language one could some sort of general-purpose variadic syntax extension, and use that to reimplement case in a library. That's really no more outrageous than the idea of overloaded operators, which by my standards have come along fairly recently. FPC will definitely not go in this direction. I know. I'm still entitled to hold that opinion. QuoteQuote from: MarkMLl on March 18, 2022, 09:45:54 pmYes, much what was anticipating. Can you put exit/continue/etc. in an anonymous function? An anonymous function can not influence the code flow of the surrounding code, cause the anonymous function can be passed outside the surrounding code's scope. OK, so it can't really replace a case. I was hoping it could effectively be inlined, which could be reasonably expected to be able to alter control flow. After all, a macro expansion can alter control flow and you're the one who repeatedly says that generics etc. are an adequate alternative to macros. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2022-03-20 11:11 Quote from: MarkMLl on March 19, 2022, 05:42:06 pmQuoteQuote from: MarkMLl on March 18, 2022, 09:45:54 pmYes, much what was anticipating. Can you put exit/continue/etc. in an anonymous function? An anonymous function can not influence the code flow of the surrounding code, cause the anonymous function can be passed outside the surrounding code's scope. OK, so it can't really replace a case. I was hoping it could effectively be inlined, which could be reasonably expected to be able to alter control flow. An inlined function can't influence the code flow of the function it's inlined into either (aside from exceptions, but those work the same as if the inlined function was called). And while the compiler currently can't inline function pointers there is nothing in principle that would stop it from inlining functions passed in as parameters as long as the function that is being called is inlined as well. Quote from: MarkMLl on March 19, 2022, 05:42:06 pmAfter all, a macro expansion can alter control flow and you're the one who repeatedly says that generics etc. are an adequate alternative to macros. I consider generics an adequate alternative to macros, because I consider marcos as an adequate solution in only a very narrow set of usecases. ---------------------------------------------------------------------- Thaddy · 2022-03-20 12:18 Quote from: PascalDragon on March 20, 2022, 12:11:01 pmI consider generics an adequate alternative to macros, because I consider marcos as an adequate solution in only a very narrow set of usecases. FPC Macros - with its halfway implementation, no parameters - you mean? Even those are more powerful than many people think. But I agree on your remark regarding generics. (My C++ work relies on its macro features, bad, but it does) ---------------------------------------------------------------------- MarkMLl · 2022-03-20 14:04 Quote from: Thaddy on March 20, 2022, 01:18:07 pmFPC Macros - with its halfway implementation, no parameters - you mean? Even those are more powerful than many people think. But I agree on your remark regarding generics. (My C++ work relies on its macro features, bad, but it does) I think it's interesting that Rust distinguishes between declarative and procedural macros. One of the more interesting bits of macro-implemented code that I've seen recently is this: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #define Py_BEGIN_ALLOW_THREADS { \                        PyThreadState *_save; \                        _save = PyEval_SaveThread(); #define Py_END_ALLOW_THREADS    PyEval_RestoreThread(_save); \                 }  MarkMLl ---------------------------------------------------------------------- MarkMLl · 2022-03-20 14:05 Quote from: PascalDragon on March 20, 2022, 12:11:01 pmAn inlined function can't influence the code flow of the function it's inlined into either (aside from exceptions, but those work the same as if the inlined function was called). And while the compiler currently can't inline function pointers there is nothing in principle that would stop it from inlining functions passed in as parameters as long as the function that is being called is inlined as well. Sorry, poor terminology on my part. I was thinking of inline or immediate expansion, rather than an inline (i.e. out-of-body) function. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2022-03-21 10:25 Quote from: MarkMLl on March 20, 2022, 03:04:05 pmOne of the more interesting bits of macro-implemented code that I've seen recently is this: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #define Py_BEGIN_ALLOW_THREADS { \                        PyThreadState *_save; \                        _save = PyEval_SaveThread(); #define Py_END_ALLOW_THREADS    PyEval_RestoreThread(_save); \                 }  What I consider quite a bit more impressive is how the developers of ReactOS managed to implement Structured Exception Handling in GCC using a support library and quite a bunch of macros. Quote from: MarkMLl on March 20, 2022, 03:05:59 pmQuote from: PascalDragon on March 20, 2022, 12:11:01 pmAn inlined function can't influence the code flow of the function it's inlined into either (aside from exceptions, but those work the same as if the inlined function was called). And while the compiler currently can't inline function pointers there is nothing in principle that would stop it from inlining functions passed in as parameters as long as the function that is being called is inlined as well. Sorry, poor terminology on my part. I was thinking of inline or immediate expansion, rather than an inline (i.e. out-of-body) function. Anonymous functions don't do anything remotely related to immediate expansion. ---------------------------------------------------------------------- MarkMLl · 2022-03-21 10:45 Quote from: PascalDragon on March 21, 2022, 11:25:36 amWhat I consider quite a bit more impressive is how the developers of ReactOS managed to implement Structured Exception Handling in GCC using a support library and quite a bunch of macros. ...although I agree wholeheartedly with you that there's a lot of things attempted with macros that would be better done with a more modern technique: they're a 55 years old concept and the art has moved on substantially. But that's not to say that there aren't areas where they're not the best or only tool for the job. QuoteAnonymous functions don't do anything remotely related to immediate expansion. Don't worry, I get it. MarkMLl ---------------------------------------------------------------------- Seenkao · 2022-03-21 10:58 Когда я столкнулся с подобной проблемой я просто перенёс кусок необходимого мне кода в другой модуль. google translate: When I ran into a similar problem, I simply moved the piece of code I needed to another module. ---------------------------------------------------------------------- lagprogramming · 2022-04-09 15:49 Quote from: MarkMLl on March 17, 2022, 01:53:38 pmNoting Thaddy's comment that something like this should have no place in the language: I've got reservations, but it's undeniably useful when writing command parsers etc. Indeed. Modifying a routine with lots of "if...then...else"s is a nightmare. A "case string of" would remove a level of ifs and would also make the code easier to be read and modified. 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 Case lowercase(trim(stringvariable)) of'string1':begin//lots of if...then if....else..if...then...else...else;end; 'string2':begin//lots of if...then if....else..if...then...else...else;end; ... 'string100':begin//lots of if...then if....else..if...then...else...else;end; else//lots of if...then if....else..if...then...else...else;end; Moving the chain of if...then...elses code in a distinctive chainofifthenelses.inc include file is of little help. Adding libraries to the executable and dynamically calling function names based on the string value is of little help because it complicates things in other parts of the code. ---------------------------------------------------------------------- MarkMLl · 2022-04-09 16:50 Quote from: lagprogramming on April 09, 2022, 05:49:15 pmIndeed. Modifying a routine with lots of "if...then...else"s is a nightmare. In that case drop the else. See https://forum.lazarus.freepascal.org/i ndex.php/topic,58917.msg439012.html#msg439012 but basically have a sequence of ifs, the one that's taken exits or breaks (e.g. out of a run-once loop), and there's an exception to make sure that control doesn't fall through unexpectedly. It's maintainable, albeit upsetting to purists. MarkMLl