About D, a template is not Tagged Union, it's a template in a module from the standard library, it's not a language feature, it makes me less interested about that language knowing that fact, they follow the same path as C++, ``std::`` crap
About D, a template is not Tagged Union, it's a template in a module from the standard library, it's not a language feature, it makes me less interested about that language knowing that fact, they follow the same path as C++, ``std::`` crap
Rust enums are a little different than in other languages that you are likely used to.
They can act like the classic C enums that you are probably used to, where they are more or less just named constants grouped together under a single type.
Then, unlike the classic C style enum, they can also hold data in them, where each variant is basically a struct with named fields and everything. They also support methods just like structs do (the methods are per enum and not per variant). In cases where you don't care about the fields names, you can define the variant as a tuple and later access fields by index.
Struct/Tuple enums are actually implemented as tagged unions by the compiler but this is completely invisible to you so you don't really need to care about it!
Enums are also totally "safe" to create and use!
Rust also has a union type which is like a C union, and you could use it to implement tagged unions (requires unsafe) if you wanted to, but in almost all cases you will just use "enum" for this purpose.
Overloading the "enum" into two different things seems like a strange choice to me but I don't know what the history is behind it, and it takes just a few minutes to figure it out so it's not a huge deal!
What's the Rust translation of this example?: https://ziglang.org/documentation/master/#Tagged-union
enum MyEnum { Ok(u8), NotOk }
fn main() {
let value = MyEnum::Ok(42);
assert!(matches!(value, MyEnum::Ok(_)));
match value {
MyEnum::Ok(x) => assert_eq!(x, 42),
MyEnum::NotOk => unreachable!(),
}
}
No unsafe to be found. The feature is there, it just has a different keyword than you might be used to -- the same way Haskell and Java both have something called "class" that mean different things.Rust unions are plain old unions that are mainly used for C interop. This is why using them requires unsafe code.
(Though too much expressability can also lead to problems, like adding nitro injection to your car.)
Why bother with slices when you can have a template? struct Slice(T) { T* ptr; size_t len; }
;)
Another example, this time with Zig, they refuse to have interface/trait, now everyone has to duplicate bogus code, even them in their std, sure it promotes the language capabilities, but at the cost of poor ergonomics, that'll prevent their growth
Many ppl talk Lisp and Nim and such. They are even more powerful. But I honestly get lost with those and not with D. Idk why, maybe my familiarity with C++ helps.
Nim is choice - in many dimensions. Many things that are built into languages even as flexible as D remain not hard-coded in Nim. E.g., it could be different now, but last I checked, D has hard-coded Associative Arrays. In Nim you can give any user type (e.g. B-Trees) the special syntax (no real meta-programming required..just generics). Also user-defined operators. Etc.
But, yeah - you need to be familiar with a base language whenever you do any meta-programming anywhere. Anyway, if you ever give Nim a try again, maybe `parseStmt` can be your gateway drug. ;-) (But I recommend starting with generics & template...)
- IDEs ecosystem (both for D and Nim) - libraries
Additionally, Nim departs quite a bit from C/C++ to look more than Python. As nice as it looks, Nim is not Python, it has a ton more qualifiers and others. It is fast, but it departs from C/C++ a lot and there is much more than it is apparent to relearn. D's path is smoother in that sense. Also, C/C++ compatibility is a problem.
Yes, I know you could say Nim is very compatible with C. But at the end of the day is a considerable investment of extra work. If it does not work, if it works half-way even if compatible in theory. I have been there many times, I code hybrid in many occassions with scripting layers that are supposed to work, and at the end, there is extra work...
Trade offs abound in most things. D is undeniably syntactically closer to C if that is the priority. I knew people in the initial Java era who insisted their next PL had to look like C. I know others who prefer Pythonic brevity and Nim is even more brief & to the point in many ways.
Compatibility-wise, Nim can also just `emit` C/C++/Javascript (like D|Nim can just emit inline assembly) - arguably max compatibility that can even work with arbitrary non-portable backend compiler pragmas, `__int128` extensions, etc. OTOH, that also ties it to limitations of backends. Possibly relevant is https://github.com/nim-lang/c2nim & https://github.com/PMunch/futhark & the rather old/probably partly stale in both columns https://github.com/timotheecour/D_vs_nim .
There are many choices in Nim. Sometimes https://en.wikipedia.org/wiki/The_Paradox_of_Choice can be a real problem - in both software or in life - and at many, many levels. :) I am not trying to challenge your own priorities or push choices on you, but to add information others may be unaware of.
Not at all. I enjoy researching this topic. Thank you!
C++ has std::variant. Not that ergonomic but usable enough if you wrap it a bit for your own use cases.