6 ms·
Personally, I find Rust syntax to be well-designed. At least, compared to any practical programming language I know. Quite a few times I was surprised that Rus
by stared 5y ago
Personally, I find Rust syntax to be well-designed. At least, compared to any practical programming language I know.
Quite a few times I was surprised that Rust breaks with some old patterns that were copied over and over in the last 50 years or so. For example: "match" instead of "switch", or the same if/else regardless if it is a statement or a value. These are small touches, but they show attention to detail.
- sireat 5y agoSyntax wise Rust seems heavily inspired by the "good parts" of Scala. - Pattern matching via "match" - if being an expression (among most things) Those are both found in Scala.
- lgessler 5y agoDidn't Scala get both of those things from ML?
- linkdd 5y agoRust syntax is weird. Weirdly good and sometimes bad. I'm currently designing my own toy language and writing the compiler (to LLVM IR) in Rust. Representing the AST with Rust's sum types is so simple. Visiting that AST through pattern matching is great. But the "enum" keyword still bugs me. The way you define product types (tuples, records, empty types) and then their implementation, just awesome. But the "struct" keyword still bugs me too. It feels "high level" with some quirks. Then you have references, Box, Rc, Arc, Cell, lifetimes etc... It feels (rightfully) "low level". Then you have traits, the relative difficulty (mostly for Rust newbies like me) of composing Result types with distinct error types, etc... It feels "somewhat high level but still low level". Sometimes you can think only about your algorithm, some other times you have to know how the compiler works. It seems logical for such a language, but still bugs me. The one thing I hate though, is the defensive programming pattern. I just validated that JSON structure with a JSON schema, so I KNOW that the data is valid. Why do I need to `.unwrap().as_string().unwrap()` everywhere I use this immutable data?
- coolreader18 5y agoBecause ideally your JSON schema validator would turn it into a type that mirrors the structure of the data. "Parse, don't validate"[0] [0]: https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/ https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va...
- linkdd 5y agoBut the Rust type system cannot fully express a JSON Schema: { "type": "object", "oneOf": [{ "required": ["kind", "foobar"], "properties": { "kind": {"enum": ["foo"]}, "foobar": {"type": "string"} } }, { "required": ["kind", "barbaz"], "properties": { "kind": {"enum": ["bar"]}, "foobar": {"type": "number"}, "barbaz": {"type": "string"} } }] } Or am I wrong?
- remexre 5y agoIn general, JSON Schemas are (wrongly, in my view...) validation-oriented rather than type-oriented (for notions of types that would be familiar to Haskell, Rust, or Common Lisp programmers). I think that schema in particular could be represented, though, as: enum Thing { foo { foobar: String }, bar { foobar: Option<f32>, barbaz: String }, }
- linkdd 5y agoWhat about user-supplied JSON schemas? You can't add types at runtime. Also, JSON schemas allows you to encode semantics about the value not only their types: {"type": "string", "format": "url"} That's something I like about Typescript's type system btw: type Role = 'admin' | 'moderator' | 'member' | 'anonymous' It's still a string, in Rust you would need an enum and a deserializer from the string to the enum.
- steveklabnik 5y agoAs the input gets more dynamic, so does the type system representation. If you want to handle user-supplied JSON schemas, in my understanding of JSON Schema, you'd have to use the serde_json::Value way: https://docs.serde.rs/serde_json/#operating-on-untyped-json-values https://docs.serde.rs/serde_json/#operating-on-untyped-json-...
- yoneda 5y ago> Quite a few times I was surprised that Rust breaks with some old patterns that were copied over and over in the last 50 years or so. For example: "match" instead of "switch", or the same if/else regardless if it is a statement or a value. These are small touches, but they show attention to detail. These are good ideas for sure, but they are bread and butter to anyone who is familiar with functional programming. The Lisp and ML families of languages have had them for many decades. The fact that more languages _aren't_ like this is what's surprising to me, given how effective they are. I love that Rust is bringing them to the masses, but what on earth took the industry so long to accept them? I guess the answer is that algebraic data types (inductively defined data) tend to be pitted against object-oriented programming (coinductively defined data), and object-oriented programming has dominated the industry for the past 3 decades. Some languages like Kotlin have tried to combine them, but personally I'd rather just embrace the former and relegate the latter to a seldomly-used design pattern, not a programming paradigm hardcoded into the language.
- dahfizz 5y agoRust reminds me a lot of Scala in that respect. Not really a functional language, but with functional goodies sprinkled throughout.
- da39a3ee 5y agoI think that there's still time for Rust to reverse the .expect(...) naming mistake. It should be deprecated, either introducing something with an appropriate name like .unwrap_or_panic(...) or just leave it to be replaced by .unwrap_or_else(|| panic!(...)) which IMO one ought to use today instead of .expect(...). Everything else is named so well and designed so well that this really sticks out.
- iudqnolq 5y agoWhy don't you like expect? It feels pretty natural to me. foo.expect("already validated")
- da39a3ee 5y agoThat reads as "I expect this to be already validated". Is that what you intended it to mean? Similarly, foo.expect("There was a problem and I had to crash") That _reads_ as "I expect there to be a problem and have to crash". But it _means_ something totally different. It means: There should not be a problem, but if there were a problem I would crash and print out this message. And the way to write that in readable code is foo.unwrap_or_else(|| panic!("There was a problem and I had to crash")) I'm sorry if I'm misunderstanding -- if I am can you explain to me how? Because I feel like my view is diametrically opposed to yours but it's really not that subjective a matter; only one of us can be right.
- iudqnolq 5y agoYou just phrase things the opposite way. I don't think it's clearly better to say the expected happy path or the unexpected sad path in a crash message. > That reads as "I expect this to be already validated". Is that what you intended it to mean? Yes > foo.expect("There was a problem and I had to crash") > That _reads_ as "I expect there to be a problem and have to crash". But it _means_ something totally different. It means: Absolutely. That's why I'd phrase it foo.expect("foo invariant upheld")
- 5y ago