It feels somewhat disingenuous to include a turing-complete meta-programming language (i.e macros) in your definition of the C++ type system.
Because vanilla OCaml doesn't have any mechanism for expressing compile-time computations, the same level of transformations aren't possible, but I wouldn't call this a limitation of the type-system, rather the meta-programming capabilities.
Although, you can somewhat approximate it with modules and functors:
module type M = sig type t val t: t end
let my_type (type a) (v: a) : (module M) =
let module M = struct
type t = a
let t = v
end in
(module M : M)
module T1 = (val my_type 123)
type t1 = T1.t
let val1 : t1 = T1.t
module T2 = (val my_type val1)
type t2 = T2.t
> It feels somewhat disingenuous to include a turing-complete meta-programming language (i.e macros) in your definition of the C++ type system.
But this is literally what a type system is about ? TS definitions don't care about compile-time and run-time ; what you call "macros" are type-level functions which are a byproduct of the expressivity of C++'s TS.
Remember that expressivity of a type system is just the cardinality of the type set you can express with it.
Type systems where you can parametrize on nothing are less expressive than type systems that can parametrize on types, which are less expressive than TS which can parametrize on meta-types, which are less expressive than TS which can parametrize on meta-types and integers (C++98, Haskell afaik), which are less expressive than TS which can parametrize on meta-types and arbitrary compile-time values (C++20, soon Rust I believe ?), which I'd guess are less expressive than full-blown dependent types but I'd need to check the exact definition
> TS which can parametrize on meta-types and integers (C++98, Haskell afaik)
Haskell also supports type-level strings and type errors, as well as arbitrary ADTs if defined with the -XDataKinds extension enabled. Not sure what you mean by ‘parametrizing on meta-types’ though.
I haven't used ocaml but I think something is possible with GADTs. Beside the example you have given shows C++ templating prowess and not its type system. In general I wouldn't call a type system that doesn't support ADTs expressive.
But GADTs are expressible in the C++ type system (thanks to templates which are just the C++ implementation of the parametrizable types typesystem-level property)
I knew someone would say that :-) ‘Slower’ is super subjective. What is the actual performance requirement? And remember that the OP thread is talking about an extremely high-performance RPC system. Sure, it may not be as fast as C++, but again, what is the actual performance requirement. You don’t go around just throwing ‘Eh, not as fast as C++’ at everything you come across :-)
Who cares? What use is measuring the objective performance difference between two solutions if no one cares about the difference? That’s why I’m talking about the actual performance requirement.
But what when people care ? I work in a field where individuals regularly spend 4 to 5 figures for a new CPU for a half-percent of single-core performance improvement ; computers will literally never be fast enough for what we want to do with them so our job is to leave exactly zero possibility for improvement through software
If you care about it, then obviously go to town on optimization, use an FPGA, whatever. But I notice you said 'CPU', which means there is a performance/cost tradeoff even in your field. Otherwise wouldn't you be using specialized hardware?
When we are talking about a general-purpose language like OCaml, then you come in talking about extreme HPC–you must realize it's not relevant in the discussion? Would you comment on threads about Golang talking about how it's not appropriate for HPC usecases?
I mean, yes, FPGAs and dedicated hardware are researched and used in that field.
The main reason CPUs are used "more" is due rather to convenience, and what people want to do not easily being doable on an FPGA ; for instance one of the often used programming languages there (Faust) just got an experimental FPGA port after 20+ years of existence.
But when talking about performance the point is to extract the absolute most performance possible of a given hardware, because you are building a product and you can only afford a.g. some ARM chip and need to get the most out of it to make your product's price fit for its target demographic (to, you know, make money for your business).
In particular, the main "competition" in that field is analog hardware which does not have "performance" issues (but others instead : an analog guitar distortion does not have latency but it does raise the noise floor in the signal) - everyone wants the best of both worlds and it is our job to make it happen
That's an incredible arrogant and close minded way to think about software. There are plenty of domains where every extra % of performance matters. Video games, HFT, robotics etc.
Even in these domains people still balance performance against the expressiveness of the language, or else why wouldn't everyone write their games/HFT/robotics in assembly for that "bare metal" performance?
For example, many popular game engines provide C# scripting engines _even though_ using a garbage collected language (even just for scripting) is slow (and throwing away % of performance) because the performance is _good enough_ for their usecases.
That's because scripts in a game are not usually a performance bottleneck if kept to best practices. And you can bet your ass both unity and unreal have some ASM in their guts.
Exactly, I mainly work on a C++ software and for my PhD rewrote all the core algorithms in OCaml... Boy that was slow, I'm never ever touching that language again for anything that needs peak performance.
I didn't realize we were exclusively talking about real-time systems? Do you think people you argue with on HN are so dumb that they would go around claiming high-level GC languages are suitable for real-time systems?
I feel like if your concern is real-time systems, you should probably say you don’t think it’s suitable for real-time systems, instead of talking about performance differences that no one really disagrees but which don’t matter in practice for most applications anyways.
Please do not argue like that. I understand you are a fan of the language, I love the OCaml language myself. But pretending execution speed does not matter is disserving the cause, especially since many people came to OCaml because it's a great trade off between execution speed, expressivity and safety.
What I actually said: what is the actual performance requirement?
I don’t get why this is such a hard concept for people in this thread :-) Obviously you should use the right tool for the job! If you have extreme HPC requirements, no one (except maybe Jane Street) is going to use OCaml for that. It’s a high-level GC language! When you come into a thread, have some basic context about what it’s about.
People are downvoting but the GP's point does not really have anything to do with type systems. I think this example is closer to macro expansion than a typesystem.
How is paramerization of types on values not a typesystem-level property ? There's definitely nothing akin to macro expansion involved since you can do type-level computations that way
I’m pretty sure the implication is that since template instances are made specific at compile time and are done so in a way that is very analogous to AST based macro expansion. Specifically, C++ templates are a programming language which runs during the compilation of C++ code that acts by producing valid C++ AST components.
I have never seen a definition of type system which cares about things being done at compile-time or runtime, or that there even is a compile-time or run-time