5 ms·
disclaimer: I haven't actually used either, just done a lot of interested reading and a little toying around. One thing that impressed me about Zig is how simp
by mumblemumble 5y ago
disclaimer: I haven't actually used either, just done a lot of interested reading and a little toying around.
One thing that impressed me about Zig is how simple the language is. I get the impression that it would take very little time to properly learn the language and become effective at it.
Rust, on the other hand, has a whole lot of complexity even without the ownership semantics. So much to learn and understand. And, in some cases, work around. It seems, from looking at others' code, that there is a very strong temptation to lean on `unsafe` instead of figuring out how to solve a problem within the constraints it normally applies.
That has me wondering if there's really all that much safety difference in practice? Simpler code is generally easier to understand, and it's generally easier to find and fix bugs in code that's easier to understand. I can imagine a world where it's a tradeoff between, "You definitely won't have any of this relatively narrow category of bug, unless of course you opt out of the static checks, which you will probably do sometimes, even though we tell you you shouldn't," and, "There are no particular guarantees, but you're generally less likely to have any of this broader category of bug."
- steveklabnik 5y ago"simple" is, unfortunately, not a simple concept, nor does everyone agree on its effects on programs written in a language that is or is not simple. Some people do believe that, let's say "conceptually parsimonious" languages (using complicated words to describe simplicity is amusing to me, sorry) do exactly what you say. Others believe that complexity inherently exists, and you can put it in the language, where a compiler can tirelessly check certain properties for you or a runtime can do magical complicated work on your behalf, or you can put it in the programs, where users have to check such things themselves. Another way I heard this expressed one time is Ruby vs Python. I once heard someone talk about how they preferred Python as a language more, because it was simpler, but enjoyed actually programming in Ruby more, even thought it was more complex, and they value simplicity. The reason is that all of that nasty ugly stuff Ruby lets you do makes you be able to make extremely nice APIs. Things you couldn't do, or just folks don't do, in Python. And therefore they ended up liking using Ruby more in practice. I suspect that this is a topic that we, as a profession, will debate about endlessly.
- dman 5y agoThere is also the notion of languages you love writing code in vs languages you like reading code in. Languages with more powerful abstraction abilities bring joy to the writer but make things tedious for the reader.
- paavohtl 5y agoI don't agree with that. For example, I think it brings me joy as a reader that I can tell at a glance from a function signature which arguments are modified and which ones are just read. Without the abstraction of mutable and immutable references I would have to read the entire source code of the function and every function it calls to know for sure what it does with the pointers. It also brings me joy as a reader that common functionality like equality comparisons or string formatting can be derived by the compiler, instead of having separate hand-made implementations for each data structure, which might have subtle differences.
- steveklabnik 5y agoTotally. I personally would not agree with > Languages with more powerful abstraction abilities bring joy to the writer but make things tedious for the reader. I find map/filter to be easier to read than a C-style for loop. Things that are conceptually denser make discussion between experts easier, even if it makes things harder for non-experts. This is why jargon exists, for example.
- dman 5y agoAh yes - that makes sense. I should have been more precise - I meant abstractions that allow you to add opaqueness (like macros and operator overloading). Again culture plays a role here too - some communities normalize such abstractions more than others. In short I believe languages that one can pick up in a couple of days and then read code where reasoning of the code is highly local would stand a higher chance of being perceived as simple.
- Jach 5y ago
- paavohtl 5y agoIn my experience unsafe tends to be used really sparingly by most users, if at all. And besides, unsafe doesn't really turn off static checks - it allows you to do a few extra things that can't be proven to be safe statically, in tightly scoped specially annotated regions. It's mostly about bending the rules temporarily, for 1-5 lines of code at a time.
- dimitrios1 5y agoSide note: Nothing is provable in rust because it does not have a formal, verifiable specification. We have a reference implementation that we believe does the things it says it does on one particular architecture. But trust, not proofs, is indeed required. >:) (don't downvote murder me, I love rust)
- steveklabnik 5y agoA subset of Rust has been formalized and proven, but you're right that we're still working on it.
- heavyset_go 5y ago> It seems, from looking at others' code, that there is a very strong temptation to lean on `unsafe` instead of figuring out how to solve a problem within the constraints it normally applies. Are you sure those examples of unsafe Rust code were written using unsafe in order to work around safety constraints due to difficulty? I ask because there are some very real and valid use cases for unsafe code in Rust that have nothing to do with the fact that writing the code safely might be more difficult.
- mumblemumble 5y agoNot sure at all - I have effectively zero working knowledge of Rust - and certainly not looking to second-guess people's motivations for using the feature. The big bias I'm working from here is that, as an outsider, I have a hard time reconciling all the big talk about how Rust makes it impossible to experience certain classes of bugs, with the existence of a known set of things that its type checker can't check, and which includes a lot of things that are difficult to avoid. One could be forgiven for thinking that the Rust community has a habit of keeping its fingers crossed behind its back when talking. I don't want to make the perfect the enemy of the good, of course. I realize the feature is there for an important reason. But it sure looks to me like Zig is also good despite being imperfect. Perhaps they're both similarly good languages.
- Ar-Curunir 5y agoNo type checker can catch all buggy programs (that involve solving the halting problem). In practice, Rust strikes a good balance: in over 120,000 LoC of Rust code that I have helped write and maintain, we have maybe 10 lines of unsafe, with performance matching or exceeding that of the C/C++ counterparts.
- tialaramex 5y ago> No type checker can catch all buggy programs (that involve solving the halting problem). It's far worse than that, the problem is that the machine can't know what was intended. The result 5 from calling sum([1,2,1,1]) makes sense, but alas this function was intended to produce the product not the sum, the inputs were supposed to be [1,2,3,4] and the desired result was 24... the machine can't hope to guess that. A program may be buggy even if it its meaning is transparent and exactly reflects its effect, simply because it doesn't reflect the intention of the person who wrote the wrong program. This quote is attributed to Babbage: 'On two occasions I have been asked, – "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" ... I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question' But that is what we wanted, even if we obviously can't have it.
- Arnavion 5y agoIs char* c_foo(char* bar) { ... } simpler than fn rust_foo<'a>(bar: &'a str) -> &'a str { ... } ? On the one hand, c_foo is shorter and doesn't use strange symbols. On the other hand, rust_foo doesn't leave you guessing on whether the returned value needs to be free()d or not, and whether the heap allocation backing `bar` can be free()d after the call or not.
- steveklabnik 5y ago(You have a tiny typo; you forgot the <'a>. Also, I know you know this, but for those that don't, this signature could be written as fn rust_foo(a: &str) -> &str { ... } but Arnavion is trying to be explicit here to make a steelman.)
- Arnavion 5y agoYeah, I fixed that typo. And yes, foo is arbitrary, so one can assume it has another * / & parameter such that the lifetimes can't be elided any more.
- user-the-name 5y agoYou are talking about the simplicity of a line of code. The topic being discussed, though, was the simplicity of the language itself.
- Arnavion 5y agoThe simplicity of the language is directly correlated to the simplicity of that line. The fact that the language makes relationships between inputs and outputs explicit is a feature of the language, because of its borrow checker, at the expense of being syntactically verbose compared to C.
- user-the-name 5y agoNot at all. A single line will use a tiny subset of language features. It will show you nothing about the overall complexity of the language, just about those things it happens to use.