4 ms·
Rust made a strange decision abbreviating keywords which are significant (pub, fn) and making things verbose where it isn't needed (separate declaration of P).
by gardaani 4y ago
Rust made a strange decision abbreviating keywords which are significant (pub, fn) and making things verbose where it isn't needed (separate declaration of P). Here's how my dream syntax for Rust would look like:
public func read(path: AsRef<Path>) -> io.Result<Vector<u8>> {
func inner(path: &Path) -> io.Result<Vector<u8>> {
var file = File.open(path)?;
var bytes = Vector.new();
file.readToEnd(&mut bytes)?;
return Ok(bytes);
}
return inner(path.asRef());
}
I have replaced pub with public, replaced fn with func, removed separate declaration for P, replaced :: with ., replaced Vec with Vector, replaced let mut with var, replaced snake_case with camelCase, added return keywords. Note that all these are syntax changes. Semantics hasn't been changed at all. One more thing would be to remove the semicolons..
Compare that to the original. Which one is more readable?
- throwbadubadu 4y agoYou complain about abbreviation of omnipresent keywords, but then allow function only two more letters? :D I think proofs well, syntax is overrated and it is all opinionated taste.. > Which one is more readable? Not seeing any difference.
- nneonneo 4y ago`impl` exists now, so you can write pub fn read(path: impl AsRef<Path>) -> io::Result<Vec<u8>> { in Rust without needing to declare P separately.
- GolDDranks 4y agoI like the real Rust syntax more, save for double colons. (And I might prefer other brackets to <> with generics) But how is that syntax of yours separating types and generics with traits? Currently `AsRef<Path>` looks like a type although it's not supposed to be one.
- scotty79 4y agoDo they really need to be separated? Does it matter all that much when you are creating a function whether parameter is a specific type or just sny type that implements specific trait?
- GolDDranks 4y agoFunctions with generics are not quite first class citizens in Rust, so there's a difference also in the type of a non-generic function and a generic function. Or rather, the generic function doesn't have a "type" as Rust understands it. (It has a higher kinded type, but Rust doesn't support those.) Here's a demonstration of the difference: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b80c4466bf61902e7a2ac3ad5a5c87d1 https://play.rust-lang.org/?version=stable&mode=debug&editio...
- scotty79 4y agoThanks for this example. I wasn't aware if that. But still no idea why I need to write: fn poly(a: impl Display) { println!("{a}"); } instead of just fn poly(a: Display) { println!("{a}"); } Can I use same identifier for type and trait at the same time?
- GolDDranks 4y agoYeah, it could be that the compiler just referred back to the definition of the name to see if it is a type or a trait. Actually, there was a plan to implement that behaviour, but it was given up in favor of the current "explicit" style. There was some fears of confusing traits and types being more confusing in the long run.
- Measter 4y agoIt matters for two reasons I can see: * Is this function monomorphised for each type passed in or is the argument passed in as a trait object? If the latter, does it implicitly fall back to monomorpisation if the trait is not Object-safe(e.g. it takes or return `Self` by ownership)? How do we specify which of the two to use when we need to for performance reasons? * Let's say we have a function with two inputs: `func foo(a: SomeTrait, b: SomeTrait)` How do I specify that both inputs must be the same type?
- rob74 4y agoYeah, that's my main gripe with Rust as well: the lack of human-readable words ("pub", "fn" and "mut" are abbreviations, not words, and "return" was even abbreviated to an empty string) and the high density of esoteric special characters.
- ssokolow 4y ago"return" wasn't "abbreviated to an empty string", it's that Rust is expression-oriented, the value of a block is the value of its last expression, adding ; turns expressions into statements, and a function with no terminal expression returns (), which serves the same role as void. fn foo(x: u8) -> u8 { let y = { let z = something(); x + z }; y } TL;DR: It's not a property of the function, it's a property of the curly braces.
- deleted 4y ago[deleted]
- Zababa 4y agoI think the original is more readable. I especially don't like "return thing;" when it could be "thing" instead, as I prefer expressions.
- Measter 4y agoOne thing you've missed here is that `let mut` is two different things: `let` is the keyword for creating a new binding, while `mut` is part of the pattern that `let` binds to. For example, you can pattern match a tuple and make one value `mut` and the other not: let (a, mut b) = //some tuple You can't just replace `let mut` with `var` because it changes the semantics of the code.
- RazrFalcon 4y agoYou're basically describing Swift: public func read(path: URL) throws -> Array<UInt8> { let file = try FileHandle(forReadingFrom: path) let bytes = try file.readToEnd() ?? Data() return Array(bytes) } Yes, the example above is not generic and not even idiomatic Swift, but it's a good glimpse into how Rust could look like. Hopefully someday Swift would become more safe, less tied to ObjC legacy and actually cross-platform. It's a shame that such a nice language is basically Apple-only.
- matklad 4y agoYou are looking for Val I think: https://www.val-lang.dev/ https://www.val-lang.dev/
- RazrFalcon 4y agoAt least Swift exists :) But sure, there are a lot of interesting languages out there. I would love to use something other than Rust, but there are simply no choice.
- baysmith 4y agoI think using . for both field/method access and name pathing would hurt readability and make name lookup more difficult. Perhaps replace :: with a backtick instead? use std; use std`fs`File; pub fn read<P: AsRef<Path>>(path: P) -> io`Result<Vec<u8>> { fn inner(path: &Path) -> io`Result<Vec<u8>> { let mut file = File`open(path)?; let mut bytes = Vec`new(); file.read_to_end(&mut bytes)?; Ok(bytes) } inner(path.as_ref()) }
- conradludgate 4y agoYou already don't need the generic syntax. You can use `impl AsRef<Path>` if you don't need to name the generic anywhere else.