Leaderboard
Popular Content
Showing content with the highest reputation on 07/14/20 in Posts
-
As @Stefan Glienke has pointed out, we have TVarRec, Variant and TValue to deal with situation of: The type of the parameter is uncertain But in addition to the above situation, open array parameters are designed to deal with even more complex situation: Both the types and number of parameters are uncertain. The most well-known case is the Format function. However, I think the OP is heading to a wrong direction to use open array parameters for simplifying the example code he's given. There is at least one better solution: procedure DoSomething(const AParam: string); overload; begin // procedure body here end; procedure DoSomething(const AParam: Integer); overload; begin DoSomething(IntToStr(aParam)); end; The overloaded procedures eliminate the use of the `if` statement and make the code simpler and easier to read. Just my 2 cents. Edit 1: Please note, 'less lines of code' <> simple, 'more lines of code' <> complexity Edit 2: One more benefit of my above alternative method - More user friendly to the clients (that uses the DoSomething procedures). Because the clients can see exactly the type of the parameters to provide, and this is exactly the advantage of statically typed languages over dynamically typed languages such as JS .
-
In the OP you also write an implementation for each different type. So where is the saving?
-
Depends. I added only 15K LOC last year to my project. A lot of time I spend thinking how to add features asked by customers to actual app logic. This doesn't have to do with old code but to old app logic and not to break old behavior. An to leave space for feature improvements because this is a 20 years old project.
-
This all seems like an over complication for little gain. Perhaps the OP could explain better what he is trying to achieve by this? As @David Heffernan said, this is worse than method overloading, and the need for that could be removed in many cases by allowing named parameter passing. IMHO, most uses of GetTypeKind in generic code is just making up for the lack of constraint types on delphi's generics.
-
Variant will accept everything and their dog which is hardly what is wanted here. @PeterPanettone This is not in any form an array but as @david berneda rightly said a union. See https://en.wikipedia.org/wiki/Union_type We already have such things in Delphi: TVarRec, Variant, TValue. However none of them can be specified to only accept a certain amount of types. If you want something like that then write a custom record type with implicit operators and a TValue as internal storage (saves you from taking care of mixing unmanaged and managed types in a proper way) Just for the lulz: {$APPTYPE CONSOLE} uses SysUtils, Rtti; type Union = record fvalue: TValue; class operator Implicit(const value: string): Union; class operator Implicit(const value: Integer): Union; class operator Implicit(const value: Union): string; class operator Implicit(const value: Union): Integer; function IsType<T>: Boolean; end; procedure DoSomething(const AParam: Union); begin if AParam.IsType<string> then Writeln('string: ', string(AParam)) else if AParam.IsType<Integer> then Writeln('integer: ', IntToStr(AParam)); end; class operator Union.Implicit(const value: Integer): Union; begin Result.fvalue := value; end; class operator Union.Implicit(const value: string): Union; begin Result.fvalue := value; end; class operator Union.Implicit(const value: Union): string; begin Result := value.fvalue.AsString; end; class operator Union.Implicit(const value: Union): Integer; begin Result := value.fvalue.AsInteger; end; function Union.IsType<T>: Boolean; begin Result := fvalue.IsType<T>; end; begin DoSomething(42); DoSomething('Hello world'); end. If you want to go funky then make it a generic type with 2, 3, 4, ... generic type parameters 😉
-
And copy the method body in each? Well, it could split that code and put the pieces into the appropriate overload. On the other hand, that is exactly what a developer would do - and that is way more readable and maintainable (at least IMHO).
-
For this case will work with Variant. procedure DoSomething(const AParam: Variant); begin ShowMessage(AParam); end;
-
New Filter Exceptions expert in GExperts
dummzeuch posted a topic in Tips / Blogs / Tutorials / Videos
I my last GExperts related blog post I wrote about the new “Close Exception Notification” expert which I just had added to GExperts. It was a hack that hooked the Exception Notification dialog. This spawned a discussion in the international Delphi Praxis forum and resulted in a rewrite of the expert. It’s now called “Filter Exception” expert and instead of hooking the dialog it directly hooks into the code that shows this dialog. Thus it prevents the dialog from being shown for filtered exceptions. Read on in the blog post. -
If we just could write class operator Implicit<T>(const value: T): TValue; ... oh wait... we can! type TValueHelper = record helper for TValue class function &&op_Implicit<T>(const value: T): TValue; static; end; class function TValueHelper.&&op_Implicit<T>(const value: T): TValue; begin TValue.Make(@value, System.TypeInfo(T), Result); end;
-
Nothing can save you at this point.
-
FreeAndNil is correct from the consumer point of view - you call the routine it frees the thing and then once it returns you have a nil reference. That it sets the reference to nil before it actually calls Free is an implementation detail to protect against potentially recursive attempts to FreeAndNil the same reference or accessing an object which is undergoing destruction and probably a result of the convoluted architecture of TComponent and Co.
-
Destructors must not raise exceptions. My personal view is that if they do then the best course of action is to terminate the process.
-
Then make it do a strict type check comparing with TValue.TypeInfo... also method overloading and distinct types is a source of errors in itself because they are always assignment compatible with their base type so that does not count as argument. I can also pass a TFileName, a TCaption or whatever to your DoSomething2 and it will happily go into the string overload. BTT if Delphi was more functional I could very well see more usecases for this in the form of monads like the maybe or either type because they can very well solve a lot of unnecessary cyclomatic complexity
-
Hi, All other components support iOS, as Android, Windows, OSX, Linux, Lazarus... the only one which doesn't support is Telegram client component. Thanks for letting me know. Kind regards, Sergio
- 4 replies
-
- websockets
- delphi
- (and 4 more)
-
I am trying to see a proper use case for this, as the example is too simplistic to make sense. What is the problem that needs to be solved? What is the duplicate work that needs to be eliminated?
-
Issue has been solved. 🙂
-
Even worse than Variant - you can pass anything to DoSomething now and it simply wont get handled (or raise an exception if you add that as else case)
-
This seems worse than method overloading to me. There you have compile time branching. Here you have to perform runtime type checking.
-
@alejandro The demo does not save the file at all. You are required to implement that. However it is quite simple. For example, in the `StoreDataAndFile` method in `Server.Resources.pas` you could use a memory stream to access the Bytes and save to a file if SameText(LParam.FieldName, 'image') and LParam.IsFile then begin Result.FileSize := Length(LParam.AsFile.Bytes); Result.FileName := LParam.AsFile.FileName; // This will save the file lStream := TMemoryStream.Create; try lStream.Write(LParam.AsFile.Bytes, Length(LParam.AsFile.Bytes)); lStream.SaveToFile(TPath.Combine(C_RootPath, TPath.GetFileName(LParam.AsFile.FileName))); finally lStream.free; end; end In this instance, `C_RootPath` is just a folder on the server where uploaded files should be saved, but you could make this dynamic based on user info in the Token for example. Hope this helps