5 ms·
The C++17 equivalent would be something like the following (not tested): using NumberExpr = int; using VarExpr = std::string; struct AddExpr; using Ex
by kraghen 9y ago
The C++17 equivalent would be something like the following (not tested):
using NumberExpr = int;
using VarExpr = std::string;
struct AddExpr;
using Expr = std::variant<NumberExpr, AddExpr, VarExpr>;
struct AddExpr {
std::unique_ptr<Expr> a;
std::unique_ptr<Expr> b;
}
Of course, this being C++, you need forward declarations and a firm grasp of the rules of incomplete types to be confident about declaring a simple AST type.
- tomjakubowski 9y agoTo completely address JoshTriplett's point, yes, you can just define another struct for the SubExpr variant to disambiguate it from the AddExpr case. Requiring this kind of wrapping is awkward compared to e.g. Rust or Haskell's treatment of sum types, which unlike C++17 and std::visit both have powerful pattern matching features built into the language. Saying this as someone who writes C++ all day: std::visit and std::variant are weaksauce.
- deleted 9y ago[deleted]
- twic 9y agoOn the other hand, the C++ way gives you an actual type for each element of the sum; you can write a function which only takes AddExpr. The Rust way doesn't (yet).
- saghm 9y agoGiven that you have to define those types manually, I don't see why you couldn't do the same in Rust; it just doesn't force you to if you don't need it
- alphaalpha101 9y agoThat's rather disingenuous, because Haskell forces you to use `newtype` wrappers for lots of things you shouldn't need them for and don't need them for in C++.
- feanaro 9y agoCan you name an instance in Haskell where newtype is conceptually unnecessary but required by the language? In the sense that you may be able to derive the same set of logical guarantees that newtype gets you without using it, in principle.