5 ms·
I don't know why this article keeps showing up on HN every other year but since it's up, I took the time to read it and fix all the outdated facts. Notably, wh
by AndyKelley 3y ago
I don't know why this article keeps showing up on HN every other year but since it's up, I took the time to read it and fix all the outdated facts.
Notably, when it was written before there was not a package manager available. Now there is, so I rewrote that section. It should finish deploying in a couple minutes.
- david2ndaccount 3y agoSince you’re updating it anyway, the very first example says "D has @property functions, which are methods that you call with what looks like field access, so in the above example, c.d might call a function.” It is true that `c.d` might call a function, but it’s not because of @property functions (which exist but are discouraged), it’s because the parens are optional to call a function/method if there are no arguments.
- k__ 3y agoPhilosophically speaking, is it really hidden control flow if a function call just happens to look like a attribute access?
- dymk 3y agoI've only seen flow control used in the context of conditional branching, so if the function contains no branches, I don't see why it would. Hidden overhead or indirection, sure, but not necessarily flow control, for the same reason e.g. indirect pointer access isn't.
- PH95VuimJjqBqy 3y agofunction calls are, themselves, branches. underneath there is literally assembly to take current state, push it to the stack, then jump into another location in memory and start executing. And then when done, do the reverse. jump back to another memory location and pop everything back off the aforementioned stack and into registers.
- dymk 3y agoYes, but that's not a conditional branch, and that's the distinction I've always seen made for flow control versus indirection
- PH95VuimJjqBqy 3y agotry/catch/finally is also considered control flow and it's not conditional, although, unfortunately I've seen people use it as a control flow mechanism. interrupts are also control flow but, again, there are no conditionals there. control flow is about the order of execution, one common way to get there is using conditionals, but it's not the only way. Having said that, even if you disagree with Andrew's wording, the overarching idea remains. You always know explicitly if the flow changes.
- Akronymus 3y agotry/catch seems very conditional to me. If there is an error condition, jump to the error handling code. Or am I missing something?
- PH95VuimJjqBqy 3y agoI could also describe a JMP instruction as "if you got here, jump to there", but just because I can doesn't necessarily mean I should.
- epcoa 3y agoBut Try, catch and throw are in themselves not conditional, they are fancy gotos with bookkeeping. Those constructs don’t typically deal with conditions. However I think the notion that “flow control” has to do only with conditionals is not a common one. FWIW the definition on Wikipedia, which aligns with my experience is not this restrictive… the lowly goto is flow control. Basically anything that controls the program location is flow control.
- Akronymus 3y ago
- zdimension 3y agoWhen reading code in a low level setting you may want to know whether one line calls a function or simply reads a field from memory. Not that it would matter that much, but it's a valid point for some. Reading a field is usually expected to not induce any control flow
- gpderetta 3y ago> When reading code in a low level setting you may want to know whether one line calls a function or simply reads a field from memory. Unless you ditch optimizations completely, it is hard to know without looking at the generated asm. Of course you can make educated guesses.
- WalterBright 3y agoThe idea in D is to make the following unnecessary: struct S { int m_field; int field() { return m_field; } void field(int c) { m_field = x; } } just to future proof the field access. Don't bother with the access functions until they are actually needed.
- zozbot234 3y agoThe actual feature that languages should implement is lenses, prisms and optics which are like properties except made properly composable and enabling high-level optimizations, for a similar efficiency to "bare" field access.
- xigoi 3y agoI’ve never heard of those. Do you have a link explaining them?
- deepsun 3y agoI found a use for the overriding field access once, when there was a large data structure bit-packed into a byte array. I didn't really need to convert it to a different data structure, but to just extract some values, and pack it back to the byte array. So I overrode the field access that operated directly on the byte array. PS: It was in Kotlin, using @get/@set, but it doesn't matter for the philosophy.
- throwawaymaths 3y agoYes. That can affect performance and also cause spooky action at a distance. Suppose someone less careful put some code in the accessor function mutates global state. Do you want to be checking all of your objects all the time to see if they are doing something counterintuitive?
- Semaphor 3y agoInteresting that this is seen as a negative, C# has getters/setters that look like property access, but I don’t think I ever heard anyone complain about this.
- shp0ngle 3y agozig and c# each scratch a different itch.
- Semaphor 3y agoYeah, of course. But the issue would still be the same in this case.
- steveklabnik 3y agoWhile the issue is the same, context can make things different. In Ruby, I love proxy objects returned from accessors. In Rust, I wouldn't even support adding accessors to the language. Different goals and objectives.
- int_19h 3y agoC# inherited it from Delphi, so there's plenty of experience showing that this is not an issue in practice. Thing is, if you don't have accessor methods (or some equivalent syntactic sugar as in D) in a OO language, you end up with them anyway, just ad hoc like Java's get/set methods. And then you still have to think about which methods that look like they're pure queries might actually mutate shared state. If anything, I would argue that explicit accessors make it clearer because in e.g. C# you can't write a method that looks like a getter (but mutates state) by accidentally naming it as such. If someone made something a property, that's because they thought its semantics are property-like, which includes not mutating global state. Sure, people will still get that wrong occasionally, just as they run mutating "get" methods, but it is surprisingly rare.
- StreetChief 3y ago"If a tree falls in the woods and no one is around to hear it, does it still make a sound?" Attribute access is reading a value, invoking a function is different (as mentioned, using a stack, etc.), although it is certainly possible a function only reads and returns a value. All that to say my answer is yes, providing flow control mechanisms makes it flow control... and falling trees make a sound!
- brabel 3y agoProbably because it's a sort of call to arms to those languages to try and improve things where Zig is currently on top :D. Some of those can't be fixed (e.g. hidden control flow, hidden allocations) but some can (e.g. I think D has an alternative allocator API, it can now compile C/C++ code as well, and I believe its package manager is trying to add support for system dependencies as well).
- WalterBright 3y agoD has a pluggable GC, if that's what you mean. It makes trying out various GC strategies easy without modifying the compiler. D also supports the following memory allocation strategies: 1. RAII 2. stack allocation 3. malloc/free 4. custom alloctors Each has its tradeoffs, you can pick the most appropriate one. The D compiler itself uses all of them :-/
- tarruda 3y agoHi Andrew. I once saw a video (at least I think it was a video) where you suggested the possibility of Zig reaching language stability in 2025. Is that still accurate?
- reactordev 3y agoThe Bun team I guess doesn't care and went ahead with 1.0 launch a few months ago. If they are willing to bet it all on zig, I'm sure it will be around for a while. It's quite mature as it stands now. Personally, I think the road to zig 1.0 should be made methodically and without any timeline.
- charlotte-fyi 3y agoI don't know that this is an endorsement of zig rather than an indictment of bun.
- reactordev 3y agoTotal endorsement - thanks for forcing clarification.
- fl0ki 3y agoI don't recommend choosing technologies this way. Elm is one of many recent, prominent examples of how years of promising language work can still leave production users stranded, both with backwards-incompatible changes that are deal-breakers for many projects, and then stalling further updates anyway even for the users still able to use the latest version. I'm not saying Zig will go the same way, I hope it succeeds. But success in industry funding is not a guarantee, successful transition to large team contributions is not a guarantee, and even if all of that does pan out, by then the language may be markedly different. Look at Rust in 2012 vs its 1.0 in 2015 and ask yourself if you'd want you and your team to have to make so many changes to production code. Ask yourself how many unknown costs you are willing to risk in exchange for whatever you believe is the actual upside of using Zig for a particular project. Sure, somebody has to break that cycle by making those bets, but be sure before deciding to be among them. Somebody else making that bet only changes the odds so much.
- dandigangi 3y agoCool to see the Bun team used Zig.
- RationPhantoms 3y agoI think most recently, I saw Mitchell Hashimoto endorse it on Twitter.
- hiccuphippo 3y agoHe's building a terminal emulator with zig: https://mitchellh.com/ghostty https://mitchellh.com/ghostty
- lioeters 3y agoBy chance, after I read your comment I found a talk he gave about his project Ghostty. Ghostty - A new terminal emulator written in Zig - https://zig.show/episodes/32/ https://zig.show/episodes/32/
- ruffrey 3y agoGreat, concise summary. Note: the original article title could perhaps be updated to include Golang as it is mentioned a few times.
- u8 3y agoWhat about the Go try/catch claim? There is no try/catch in Go. Returning errors and values is closer to Rust and Zig than D and C++.
- TwentyPosts 3y agoGo has panics. You can unwind them, and recover from them. Using these for control flow is heavily discouraged and therefore it's rarely ever an issue, but they are a type of exception handling, or at least very close to that.
- cesarb 3y agoRust has panics too, which also unwind, and you can also recover from them; they are also a type of exception handling. Unless the project was compiled with panic=abort, in which case they don't unwind at all and you can't recover from them; the existence of the panic=abort option means one cannot reliably use them for control flow, which makes it harder to abuse. But even then, you still have to make sure your code is "panic safe" when writing library code (usually through clever use of RAII guards, instead of expecting the code flow to always reach the end of a function).
- AndyKelley 3y agoAlso worth noting is that while they are discouraged, the very same Go devs who discouraged this pattern chose to use it in the standard library for basic things.
- StreetChief 3y agoNew people will constantly be finding zig, and they will constantly be wondering why they should pick up zig, they will find that reference, and share it to educate others! You can see this happening with the duplicate stories that show up on Hacker News; in general, it's a good thing: “There are only two kinds of languages: the ones people complain about and the ones nobody uses.” ― Bjarne Stroustrup