7 ms·
I'm excited about Zig. It strikes the perfect balance on many points. "I happen to agree on type first, disagree on single return (and it's a shame Zig doesn't
by jorangreef 8y ago
I'm excited about Zig. It strikes the perfect balance on many points.
"I happen to agree on type first, disagree on single return (and it's a shame Zig doesn't seem to be on the radar especially because of this)"
Can you clarify what you mean by this?
- ikfmpwdsoz 8y agoI tried to love Zig but the lack of destructors are killing me! They're such a useful tool for resource management, and apparently they weren't added in order to make all control flow "explicit" or something.
- jorangreef 8y agoTake a look at Zig's "defer" and "errdefer": https://ziglang.org/documentation/master/#defer https://ziglang.org/documentation/master/#defer
- gmueckl 8y agoThis seems equivalent to scope(exit)/scope(success)/scope(failure) in D. The drawback of this construct is that you need to repeat 2 or 3 lines of code each time you need safe cleanup or a commit/abort type of construct. This can become pretty repetitive pretty fast.
- Paul_Diraq 8y agoI wish D had copied pythons with statement (without the scope escape) and not used the with statement for destructuring. The nicest thing: you can throw in the exit method without the runtime falling over itself.
- gmueckl 8y agoI totally missed that Python has this. This seems like the saner sibling of C#'s using/IDisposable construct. You can do a kind of RAII in D when you use structs instead of classes because these are stack allocated and have a suitable lifetime.
- edflsafoiewq 8y agoThey are not comparable to RAII, see my comment above. Even the fact it has to bifurcate into defer and errdefer suggests that it lacks the generality to replace a totalizing resource management solution.
- notacoward 8y agoNo, they're not the same as your beloved RAII, but this isn't an object-oriented language so it doesn't have destructors. For the third time, what better solution do you propose for a non-OO language?
- notacoward 8y agoI've never actually used Zig (yet), but I think their choice is reasonable. It's not an object oriented language. Using destructors for resource management in such languages is great, but I've also seen a lot of C++ code that abuses the object-lifetime machinery. The most common is lock pseudo-objects, which "exist" only so that they can be released via a destructor when they go out of scope. Those aren't real objects. They don't contain any data. They're abstractions, which should be dealt with with other guard/context language structures. I'll admit that "defer" is a bit low-level, but it does handle most resource-release use cases in a way that's consistent with the rest of Zig. What non-object-oriented approach would you suggest instead?
- jcelerier 8y ago> Using destructors for resource management in such languages is great, but I've also seen a lot of C++ code that abuses the object-lifetime machinery. That's not abuse, that's the most important pattern in C++ (RAII). You mustn't think of C++ "objects" as Java or C# or Smalltalk objects - they are not, they are deterministic resource managers before everything.
- notacoward 8y ago> You mustn't think of C++ "objects" as Java or C# or Smalltalk objects As long as people persist in calling them objects, and use all of the other object-oriented concepts/terminology such as classes and inheritance, people will expect them to be objects. That's not unreasonable. It's absurd to look down your nose at people who are taking you at your word. These other uses are hacks. If you want to be able to attach something to a scope that's great, actually it's a wonderful idea, but just be honest about it. Make scopes a first-class concept, give things names that reflect their scope-oriented meaning and usage. Python's "with" is a step in the right direction; even though the implementation uses objects, they're objects that implement a specific interface (not just creation/destruction) and their usage is distinct. That separation allows scope-based semantics to evolve independently of object-lifetime semantics, which are already muddled by things like lambdas, futures, and coroutines. Tying them together might be an important pattern in C++, but it's also a mistake. Not the first, not the last. Making mistakes mandatory has always been the C++ way.
- notacoward 8y agoMultiple return has two distinct use cases - to return multiple actual values, or to return an error status along with an actual value. Many languages can handle both cases by making it easy to create and return a list/tuple/whatever, and that satisfies both cases well enough for me. Others provide Optional or Error types which satisfy only the second case but do so in an even more concise way (no packing and unpacking of those lists/tuples/whatever). Zig is in that category, with some additional twists like errdefer and how null is handled. I'm not 100% sure I'd make the choices they did, but I think those sections of the Zig documentation are well worth reading to spur more thoughts about alternatives to C-style single return or exceptions. https://ziglang.org/documentation/master/#Errors https://ziglang.org/documentation/master/#Errors https://ziglang.org/documentation/master/#Optionals https://ziglang.org/documentation/master/#Optionals
- romeisendcoming 8y agoReturn status and data is a great argument for multiple value returns but it's simple enough to do in C. You just need an ADT and interface. Who hasn't done OO in C with mixed results?
- notacoward 8y ago> You just need an ADT and interface. Yes, you can do that, but it's always going to be far more cumbersome than native multi-value return would be. Even in the simplest case (stack allocation in the caller), you have to define a new struct that has no other purpose, in a place visible to both caller and callee. You also have to refer to the status and value as struct members rather than simple variables. That's already worse than using a return value for the status and a reference parameter for the value. I guess you could say that multi-value return is just syntactic sugar for more reference parameters. That's mostly true at the source level, but at the object level not quite. Using a reference parameter requires an extra stack operation (or register allocation) to push the parameter's address, in addition to whatever was done to allocate the parameter itself. Then the callee has to access it via pointer dereferences. With true multi-value return neither is necessary. The exact details are left as an easy exercise for any reader who knows how function calls work at that level. (BTW yes, interprocedural optimization can make that overhead go away, but a lot of code is written in C specifically to avoid relying on super-smart compilers and runtimes.) Multi-value return isn't a huge deal, though. I appreciate having it in Python, but in almost thirty years I rarely missed it in C. While I wouldn't necessarily oppose its addition, I think it's more in keeping with C's general spirit of simplicity to leave it out.