Hacker News new | ask | show | jobs
by mattnewport 2716 days ago
A bit of a test case for me, coming from the domain of games / 3D graphics programming, as to whether a language has a 'sufficiently powerful' generics feature set is whether it is possible to implement a generic 'short vector' type as used in any type of graphics programming. I think 'good' generics / metaprogramming support should let you meet most of these goals in a generic 'short vector' type:

- Support 'n' dimensional vectors (2, 3 and 4 are the only ones commonly used in 3D graphics and games).

- Support a choice of underlying element type (at least float, double and int but it's handy to be able to support custom types like a fixed point or rational type too).

- Support operator overloading for natural expression of things like adding two vectors.

- Be very close or identical in performance to the equivalent hand written variant for every combination of dimension / element type (excluding optimizations for particular SIMD element widths etc.)

- Not be significantly worse for debugging than the equivalent hand written code (this is as much a tooling issue as a language issue).

It's possible to meet all of these requirements in modern C++ without using any particularly exotic metaprogramming functionality. It's impossible in C#. I don't know of any other language that meets these requirements as well as C++ although I'm not really familiar with the facilities offered by e.g. Rust.

2 comments

Makes sense, yeah. I think that's reasonable. You can do this in Rust (https://www.nalgebra.org/vectors_and_matrices/ as an example), but one caveat: the n-dimensionality aspect isn't as nice (see the "Type-level integers" section of that doc) until "const generics" lands; that's completely orthogonal from the "generics" vs "templates" discussion, except that it's easier to implement (from the compiler's perspective) via templates.
None of these require C++'s gradual typing- the only real reason C# can't meet them is that it lacks value parameters to generics, and perhaps some limitations to its value types.
This comment wasn't about gradual typing, it was about power / generality of generics / metaprogramming support. C# fails at this in more ways than lacking value parameters and having limitations on value types.

There is no efficient and syntactically pleasant way to work with numeric types generically for example (I can't write 'a + b' and have it work for any types that provide operator+). That doesn't require C++ compile time duck typing (you could mandate something like C++ Concepts to specify a numeric interface, I believe this is sort of what Haskell typeclasses do) but it's easy, efficient and syntactically pleasant to do in C++.

The limitations of C# generics bite it in other ways too - the members of Enumerable are useful and the syntax is ok (not as nice as F# or C++ Ranges) but C# can't match the performance of C++ Ranges given the way they are implemented. They also get bitten by the operator problem - look at how Enumerable.Sum() has implementations for every built in numeric type and doesn't out of the box support your custom Numeric type.

Fair enough, typeclasses/traits were what I had in mind here. You're right that C# doesn't have a common interface to constrain your generics with for operator+/etc.