-
Content Count
2558 -
Joined
-
Last visited
-
Days Won
150
Posts posted by Uwe Raabe
-
-
1 minute ago, David Schwartz said:There's a compiler switch that overrides this, so it's not really "guaranteed".
The compiler switch makes it evaluate either all parts, which is perfectly valid in the first place, or evaluates from left to right, which is exactly what we want when writing
Result := Condition or Result;
So whatever that switch is, Condition is evaluated first.
-
Make the function a static class function of a record:
type TMyPassHandler = record public class function Pass<T:record>(const Value: T): Boolean; static; end; class function TMyPassHandler.Pass<T>(const Value: T): Boolean; begin Result := False; { do whatever is needed } end;
Most of the time the compiler should be able to infer the proper type, so a call would look like:
TMyPassHandler.Pass(myRec);
- 2
-
36 minutes ago, Mahdi Safsafi said:Also what about that ?
Result := Condition or Result;
That is a valid approach for the Result := Condition part, but in the original example Result is a string while Condition is a Boolean;
-
if Condition then Result := True;
Result := Condition;
These are not the same! What if Result is true before that line in the first and in the second case?
- 1
-
Write your own procedure:
procedure MPC(var Result: string; const Value: string; Condition: Boolean); // MPC stands for Mike's Preferenced Condition begin if Condition then Result := Value; end; ... // call MPC(Result, 'N', Property = 'A');
You can even make it a function, but then you must provide a value for the false condition, too.
- 1
-
1 minute ago, Attila Kovacs said:So avoid variables and everything should be ok in anon methods?
Lars also showed a valid approach in his blog post. There is nothing wrong with using variables. As always you have to know what you do.
- 1
-
Now I have seen the link to the sample code. Will look into it.
- 1
-
I imagine what is happening and I assume it to be expected behavior, although I admit one has to know how variable capturing works to get it. It is even documented (Variable Binding Mechanism)
QuoteNote that variable capture captures variables--not values. If a variable's value changes after being captured by constructing an anonymous method, the value of the variable the anonymous method captured changes too, because they are the same variable with the same storage.
There is still a lot of guessing about what is THandlerClass, OnHandle and how AddHandler is defined and what it does with its parameter, so it is difficult to give a detailed analysis.
- 1
- 1
-
1 hour ago, John Kouraklis said:Why don't you use TFormatSettings? It should load the locale of the machine
The file might have been created on another machine.
-
46 minutes ago, dummzeuch said:I assume that the decimal separator is either a comma or a dot. I try to guess which one or is.
One criterion: The decimal separator is only allowed once.
function GuessDecimalSeparator(const Value: string): Char; { Assumes that the decimal separator is the last one and does not appeat more than once. Only dot and comma are treated as possible decimal separator. } const cSeparators: array[Boolean] of Char = ('.', ','); // possible decimal separators var idx: Integer; begin Result := cSeparators[False]; // default if none of the separators is found - alternative "True" idx := Value.LastIndexOfAny(cSeparators); if (idx >= 0) then begin Result := Value.Chars[idx]; if Value.CountChar(Result) > 1 then begin { if it appears more than once we use the other one } Result := cSeparators[Result = cSeparators[False]]; end; end end;
- 1
-
35 minutes ago, dummzeuch said:Will also fail on '1.000.000'.
Define "fail". For German language settings it returns a comma, which is probably correct in most cases.
If the choice is either comma or point, the algorithm can be adapted to that. Otherwise the task is just not fully defined for all inputs.
So what would you call a correct result when the decimal separator is not part of the string?
- 1
-
function GuessDecimalSeparator(const Value: string): Char; { assumes that the decimal separator is the last one and does not appear more than once } var idx: Integer; begin idx := Value.LastIndexOfAny(['.', ',']); // possible decimal separators if (idx >= 0) then begin Result := Value.Chars[idx]; if Value.CountChar(Result) = 1 then Exit; end; Result := FormatSettings.DecimalSeparator; // Default end;
- 1
- 1
-
I expect to see no splash form on the taskbar in the first place - neither with or without icon. When I create a new VCL application I have an additional line after Application.Initialize which leads to that behavior:
Application.MainFormOnTaskbar := True;
- 1
-
In Delphi a set is denoted with square brackets. Unfortunately a constant array is also denoted with square brackets. I have to admit that I am not happy with this language design decision either.
The term [10] as well as (i being an integer) can be both a set or array constant. There is no rule for the compiler to choose one or another. There are scenarios where the compiler chooses different than the developer intended.
If you feel that the compiler is doing wrong here, please open a bug report with this example.
-
Probably because in the second case "[10]" is seen as a set constant by the compiler. It works if you declare a variable with a proper type:
var b: boolean; a: array of Integer; r: TMyRecord2; begin try a := [10]; r := r * a; // this line is compiled b := r = a; // this line is not compiled except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
- 1
-
10 minutes ago, Stefan Glienke said:I like using SourceTree (after the 2.x disaster in 3.x it's usable again).
As I am still looking for a usable GIT client that matches the ease of the TortoiseHG workbench, I should probably evaluate SourceTree again.
- 1
- 1
-
The components you see in the Form Designer are those inside the BPL loaded at design time. As long as you don't re-compile this BPL you will work with the old version of the component.
This can be different than the version compiled into your EXE, as long as the new source files are found somewhere in your search path.
- 1
- 1
-
This is an class approach. The benefit is the full encapsulation of the private parts inside the implementation section.
unit uGlobalData; interface type TGlobalData = class type TValue = record ValName: string; ValInProject: boolean; end; public { these should probably be properties instead } Id: Integer; RecName: string; Values: TArray<TValue>; procedure PrepareGlobalRec; virtual; abstract; end; function GlobalData: TGlobalData; implementation type TGlobalDataImpl = class(TGlobalData) private type TLocalRec = record LocalRecStr: string; // ... end; procedure LocalProc1; procedure LocalProc2; var LocalStrVar: string; LocalRecVar: TLocalRec; public procedure PrepareGlobalRec; override; end; procedure TGlobalDataImpl.LocalProc1; begin end; procedure TGlobalDataImpl.LocalProc2; begin end; procedure TGlobalDataImpl.PrepareGlobalRec; begin // prepare GlobalRec data LocalStrVar := 'local test'; LocalRecVar.LocalRecStr := 'test'; LocalProc1; LocalProc2; end; var GlobalDataInstance: TGlobalData = nil; function GlobalData: TGlobalData; begin if GlobalDataInstance = nil then begin GlobalDataInstance := TGlobalDataImpl.Create; end; Result := GlobalDataInstance; end; initialization finalization GlobalDataInstance.Free; GlobalDataInstance := nil; end.
- 1
-
This has been the case for quite a while. The URL points to the defunct QualityCentral.
-
1 hour ago, Stéphane Wierzbicki said:maybe an IDEFixpack side effect
Indeed! I can reproduce it with IDEFixPack installed.
-
Cannot reproduce. Datatype dropdown list contains unique values here.
-
I wonder how this folder is going to be used as Shared folder. For a non-admin installation that should rather be %APPDATA%\Raabe Software\Shared and not %APPDATA%\Raabe Software\MMX Code Explorer. On the other hand I can imagine some buggy setup scheme from my side.
So whatever that registry RootDir entry points to, copy the Indexers folder into that folder and you should be done.
I will investigate the setup for any glitches - or better - rethink the folder architecture in general.
- 1
-
The Indexer templates are expected in the Indexers sub folder from the shared folder set in registry under HKEY_CURRENT_USER\Software\Raabe Software\Shared\RootDir.
It is quite possible that something went wrong during the installation and the indexer files were not copied to that folder. I will check the setup for that.
-
9 hours ago, Mike Torrettinni said:Settings related screens, the logic says: create once, use for the life of application and all the values that developer set once, will be there until closing.
For these cases I prefer moving the settings to a separate settings class independent from the settings form. Then I can create and initialize an instance of this settings class at startup, load the settings from some storage and adjust with some command line parameters. Then the settings are available all over the application without having to rely on the settings form creation. I often have the case where I need access to the settings long before the main form is created. This would be hard to achieve using the settings form as the central storage for the settings.
- 4
Complete Boolean Evaluation
in Algorithms, Data Structures and Class Design
Posted
The more subtle cases are when code requires to switch that off to work properly and someone compiles with that switch on: