1. The generic type is constrained, but cannot be used for class references?
TBase = class
constructor Create; virtual;
TGenericWrapper = class
TBaseClass = class of TB; <– [dcc32 Error]: E2021 Class type required
Is there any logical reason for why this should not be possible?
2. Constructing an instance from a generic type does not flag construction of a class with unimplemented virtual abstract methods. This one I can understand, but it still is annoying. I guess I could factory functions to work around it.
24 thoughts on “Generic surprises”
the more I use generics, and the more I think they should have been just some kind of macro with less constraint. A kind of hidden copy/paste of code that can compile or not when used, but not when declared.
I gather there is a reason, yes, Lars Fosdal. My opinion is that making a class reference would also imply that you can have specialised class references with constraints and checking correctness would become extremely convoluted, to the point it may require multiple passes.
This is part of why I create a base, non-generic class to use for class references.
Andrea Raimondi – The constraint is already explicitly referencing the class type in the generic type parameter. As with any class of type, only methods declared in that specific type would be accessible. Declaring the “class of” directly on TBase outside the generic class was good enough, but I was surprised that I couldn’t put it inside the generic class – since it has no use outside it.
Most missing features in the Delphi language have only two logical reasons which are “no resources” and “don’t want”
Paul TOTH Noooooooooo. The compiler should have been properly tested.
Jeroen Wiert Pluimers it’s not only a compiler question, a macro with clear compilation error is easy to understand and debug…while generics are sometime in a high level of abstraction, far from what the coder want at the end…with a macro you can always unroll the code for the specific case and find the mistake…with generics you can stay bocked at the declaration part before any uses case.
Paul TOTH Generics were not implemented purely as templates for a good reason. However due to other limitations in the compiler and the language design itself they suffer a bit. I surely don’t want to have TMP in Delphi!
Stefan Glienke I think it was to play in dotNet garden, but it is not a good idea. especially because dotNet (with generic support at the framework level) is no more a Delphi target platform
It was not, it was to combine the benefits of templates and true generics and not get all the C++ template madness. However what C# does with its generics (like being able to contruct closed generic types at runtime, not get binary code bloat) is deeply integrated in the CLR to make it possible.
The problem with the Delphi implementation is because the language, runtime and compiler were not designed with generics in mind so the current implementation is just slapped onto it. For that being they work reasonably well but could use some improvement in their implementation (see for example https://quality.embarcadero.com/browse/RSP-18080) and feature wise (like more constraints, better support for dealing with differently shaped types – which was improved a bit with the intrinsics like GetTypeKind) – fun fact: C# 7.3 added support for enum constraint and for C# 8 they are working on way more powerful ways to constrain generic type parameters on their shape and feature. However the rather rapid development of C# in the recent past is only possible because their compiler rewrite now allows them without risking breaking things left and right and having to implement everything twice.
Generics go a long way to facilitating generic programming. But for me at least there is big gap which is numerical programming.
Suppose I have an algorithm that does not vary depending on the type of base scalar being used. For instance, it could be an algorithm that is identical for real and complex scalars. I can write that algorithm once using templates, but generics are no use to me.
That’s a very real problem for me.
David Heffernan The current constraints leave a lot to be desired – such as constraining to T being an enumerated type.
I am curious: Is it possible to do real/complex scalars generic code in C#?
Lars Fosdal Not if you care about performance
Lars Fosdal No, because there is no way to constraint the type to anything that would be needed (like supported operations).
Which is what they try to address in C# 8 – see https://channel9.msdn.com/Blogs/Seth-Juarez/A-Preview-of-C-8-with-Mads-Torgersen#time=32m11s
P.S. After viewing this again, he only touched on the subject but he wrote a long proposal on that topic on github, see https://github.com/dotnet/csharplang/issues/164
Templates solve this problem beautifully IMHO
Lars Fosdal David Heffernan needs to slip loose from constraints and embrace the freedom of dynamic typing; then he can have his single algorithm/multiple number types. 🙂
David Heffernan C++ templates are Turing-complete and can get really complex. Here’s a great guide to template metaprogramming that some people will love and some people will think “thank goodness Delphi chose generics!”
github.com – MCGallaspy/dr_strangetemplate
FWIW my own view is we should expand constraints and compile-time checks (functions, if branches that are evaluated at compile time, etc) giving much of the power of type and other checks, without something as complex as templates.
David Millington Personally I don’t much care how things are implemented. What I care is that I can solve my problems. If generics can be extended to allow me to write:
X, Y, Z: T;
Z := X + Y;
where T is the generic type, and + is an operator overload, and the compiled code is efficient, then that’s fine.
I’m not aware of any language where that can be done with generics. It can be done today in languages that have templates.
Joseph Mitzen Dynamic typing is bad. Good type inference is good.
Joseph Mitzen performance won’t be acceptable
Lars Fosdal dynamic typing is good in some situations
Lars Fosdal From function overloading to interfaces to casting to generics and templates, design patterns, etc., statically typed languages are filled with construct upon construct to try to get around the fact that they’re statically typed. Humans end up spending massive amounts of time turning code they know will run into code that a compiler will believe will run, all to avoid errors that basically never happen. Meanwhile, the time they spend appeasing the compiler is longer than the time it would take to fix type errors, and the scaffolding code itself introduces more bugs.
To quote Robert C. Martin,
” I’ve been a statically typed bigot for quite a few years. I learned my lesson the hard way while using C. Too many systems crashed in the field due to silly typing errors. When C++ came out, I was an avid adopter, and rabid enforcer of strong typing. I scoffed at the smalltalkers who whined about the loss of flexibility. Safety, after all, was far more important than flexibility — and besides, we can keep our software flexible AND statically typed, if we just follow good dependency management principles.
“Four years ago I got involved with Extreme Programming. I liked the pragmatic emphasis it placed upon developing software. I also liked the emphasis it put on testing. Since then I have become test infected. I can no longer concieve of writing software without using test driven development. I can’t imagine not having a comprehensive suite of unit tests to back up my development.
“About two years ago I noticed something. I was depending less and less on the type system for safety. My unit tests were preventing me from making type errors. The more I depended upon the unit tests, the less I depended upon the type safety of Java or C++ (my languages of choice).
“I thought an experiment was in order. So I tried writing some applications in Python, and then Ruby (well known dynamically typed languages). I was not entirely surprised when I found that type issues simply never arose. My unit tests kept my code on the straight and narrow. I simply didn’t need the static type checking that I had depended upon for so many years.
“I also realized that the flexibility of dynamically typed langauges makes writing code significantly easier. Modules are easier to write, and easier to change. There are no build time issues at all. Life in a dynamically typed world is fundamentally simpler.
“Now I am back programming in Java because the projects I’m working on call for it. But I can’t deny that I feel the tug of the dynamically typed languages. I wish I was programming in Ruby or Python, or even Smalltalk.
David Heffernan With JIT and other advances, that dynamically typed code can end up being almost as fast as C++ today.
ibm.com – A Speed Comparison Of C, Julia, Python, Numba, and Cython on LU Factorization (IT Best Kept Secret Is Optimization)
Joseph Mitzen I like this article: blogs.perl.org – What to know before debating type systems | Ovid 
I still don’t like dynamic typing – especially not the weak kind.
Joseph Mitzen That article you link to doesn’t conclude what you think it does. It basically says exactly the same as me. The raw Python code is slower than raw C code, and instead recommends using scipy for the matrix solve. That code is Fortran of course.
I don’t see any JIT compiling there. Did you link to the wrong article?
Perhaps you should get some first hand experience of writing such algorithms.
You must log in to post a comment.