> (type)expression is annoying to parse

Ehhh I think it's not that bad, no harder than arithmetic expression parsing certainly. It's just one more grammar rule. Plus Rust supports everything that's needed already because of operator overloading.

> In any case, destructors and move semantics gives most of the benefits of context managers.

They (well, destructors anyway) are less explicit though. When you use a context manager in Python you know it's cleaning things up. When you "use" a destructor in Rust you usually don't ever know you did. This can get you into trouble if you're relying on RAII to cleanup after you: you can get a handle to things and then enter a long loop or call chain. Sure you can avoid that by calling `drop`, but if context managers were the idiom this kind of thing would never be an issue. But I admit the difference is pretty small -- and in fact might be surprising to systems programmers so probably it's the right choice (even if destructors themselves are kind of mind boggling).

> This is just consistency. Why have block-as-an-r-value as the only case when a semi-colon isn't allowed? Furthermore, there's places for blocks that are formally r-values, but perfectly legitimately have type (), like the arms of match blocks and bodies of closures. And, lastly, not having a special case like this makes writing macros easier.

Well mostly I would deal with all this by removing "everything is an expression". Match blocks would just be regular blocks like `switch` in C or what have you, and so on.

> Match is necessary for working with `enum`s, and enums are great tool for avoiding allocations (e.g. Option<T> instead of a T* that's possibly null) and generally for guiding towards type safety. Having a single entity that does the complete deconstruction of an enum is important with move semantics, or else one would be forced to do a lot of extraneous nested "as_mut"/"is_none" etc. checking, especially for nested deconstructions.

Well switch/if/else have worked fine for a long time; and now C/C++ compilers warn you on missing branches when switching on enumerated values (Rust won't if you have a fallthrough case). But I prefer switch/match to if/else because if/else are too general for just switching on a variable (which is why I'm very dismayed at match guards -- they wholly abrogate the benefit of match over if/else), and I think switch's behavior is generally too restrictive (this is the only problem I have with switch provided you use proper blocks instead of the souped-up goto it really is). Match has so many features baked into it that every time I see one I have to stop and take a deep breath. It's very much geared towards writing and not reading, I feel.

> [match guards are] very convenient for conditionalizing based on enums... and yes, it's unrestricted, but that's for consistency: why restrict it?

I kind of went into this above, but in a language that doesn't have a good match/switch (like Python) you'll frequently run into code like this:

if value == 1:
# do a thing
elif value == 2:
# do a thing
elif value in range(3, 20):
# do a thing
elif totally_unrelated_function_call() and other_thing == 98:
# do a thing
elif value >= 20:
# do a thing

But when you have switch, you can't run that 4th conditional and have it shortcircuit the 5th conditional. Switch is, in that way, very much specifically for breaking down enums, so when I see one I can restrict my thinking to that variable and that variable alone.

Unless, of course, we're using match guards. Then I have to consider everything again, and I wonder why we're not just using if/else. Of course I understand that match is an expression so that's another "benefit", but if/else also have that behavior in Rust and I would get rid of that anyway.

> Do you don't like binding any variables in a match, or specifically doing it with @? I don't think you can use a let to emulate it, at least not without a lot of clunkiness.

I don't think this is too bad:

fn main() {
println!("Tell me type of person you are");

let my_age: age();

match my_age {
0 => println!("I'm not born yet I guess"),
// Could `match` 1 ... 12 directly but then what age
// would the child be? Instead, bind to `n` for the
// sequence of 1 .. 12. Now the age can be reported.
1 ... 12 => println!("I'm a child of age {:?}", my_age),
13 ... 19 => println!("I'm a teen of age {:?}", my_age),
// Nothing bound. Return the result.
_ => println!("I'm an old person of age {:?}", my_age),
}

> Rust does have a file-based approach.

Sure but I guess my argument is the file/folder hierarchy approach combined with mod is a little clunky. I think it's clearer to just declare a module at the top and let people use whatever folder structure they want.

> Visibility/access control has been an endless argument in Rust.

Hah, OK fair. I guess you can't please everyone ;)

> I take it you want the idiom to be baked into the language to be slightly nicer.

Yeah like `type` or some such. It's a little weird to kind of overload struct this way (and don't get me going on enum haha -- it's a variant!!!!!!!!!!! it's a union!!!!!!! it's anything other than an enum!!!!!).

> People complained endlessly about the impenetrable sigils.

Oh yeah, I was one of them. But my complaint was all the extra sigils. There was `~` for an owned pointer, `@` for GC pointers, and the `mut` suffix for mutable versions, and the worst sin of all was that `*` was strictly for unsafe pointers. So the one you're most likely to recognize is the one you'll basically never see. Booooo.

But I guess mostly what it comes down to is that "everything is an expression" greatly weirds the language for me, match is a super feature, and there are weird tricks that don't really make sense like "Use _ as the default case in a match" and "if you're destructuring in a match and you don't care about some fields, just use `..`". At least in switch, the default case is called "default".