Hacker News new | ask | show | jobs
by pcwalton 4088 days ago
> Apart from the Rust's usual rule to invent some abbreviations, but only apply them half the time.

Do you have an example?

> Then "types start with an uppercase letter" except when the language creators break their own rule.

They always start with a capital letter, except for built-in types or FFI bindings to libraries such as libc where the original types used a lowercase letter. This convention is exactly the same as Java.

> Then the fun "sometimes we use () and sometimes we use [] to do practically the same thing".

I've never heard this before. Do you have an example? () is used for function calls, grouping, and tuples, while [] is used for array literals and array indexing.

> Then the various insanities with ::.

The double-colon is very useful so that you can tell the difference between module lookup and field projection/method calling. Early Rust used . for module lookup, and it was confusing to tell at a glance whether a function was being called or a method was being invoked.

> Then Generics. How many examples of languages which tried to use <> for Generics do we actually need before people learn the lesson?

Using square brackets like Scala wouldn't actually help with the ambiguity, because it would be ambiguous with array indexing. The only syntax I've seen that actually solves the ambiguity is D's `!()`, which was deemed too unfamiliar. Angle brackets were chosen because they are familiar and aren't really any worse than the other mainstream options.

> I really wished some people took Rust, and wrote a new frontend to get rid of all the pointless inconsistencies and other "C did, so it has to be good"-isms (like_all_this_underscore_stuff or the ridiculous abbreviations)

The underscore naming convention was actually taken from Python's PEP 8. Rust doesn't really have any more abbreviations than most other languages at this point.

3 comments

> > Then the fun "sometimes we use () and sometimes we use [] to do practically the same thing".

> I've never heard this before. Do you have an example? () is used for function calls, grouping, and tuples, while [] is used for array literals and array indexing.

Maybe referring to the ability to use either type of brace with macros?

Yeah, you can use any type of delimiter with macros, but I think that's an important feature, especially since macros can expand to declarations. Early versions of Rust required parentheses for all macro invocations, and that looked really ugly for anything that looked like a block. Delimiter interchangeability is a feature from Racket that works really well when it comes to macros and I'd hate to give it up.
Agreed. They allow you to naturally create vectors with the bracket delimiter `vec![1, 2, 3]`, create spawn-like macros with the brace delimiter `spawn { code }`, and in the normal case just use parentheses `println!("testing")`
> () is used for function calls, grouping, and tuples, while [] is used for array literals and array indexing.

Array indexing is a function call, because an array is a function from its index set to the set of the values the array stores, or -- equivalent -- a partial function from integers to the value set.

Scala gets this right.

> Scala gets this right.

I don't know, I never liked how all FunctionNs are sort of "unofficial" partial functions (because they may throw), and PartialFunctions are then made a subtype of FunctionN, because they have an extra method where you can ask whether they are defined at given points. Especially since throwing seems to be falling out of favor in Scala, being replaced by Try[] return types.

This is an orthogonal issue. Arrays are clearly partial functions. The Try[.]-vs-exceptions issue is to do with the question whether failures should be reflected in types (the Try[.]-option) or not (exceptions). There are good arguments for and against both options, but both options go well with the understanding that arrays are functions and indexing is function application.
I don't think anything's much orthogonal to partiality of functions in languages with strong type systems, unfortunately :)

You wrote that array indexing is "a partial function from integers to the value set". If we're to take the suggestion seriously, then the practicality of it depends on how partial functions are represented in the language. Which itself is certainly not orthogonal to the Try-vs-exceptions issue.

I'm not sure I can agree. I didn't say that the type of the array function is independent of the choice of error propagation mechanism. If you think an array is a partial function from integers to some value domain, say A, then in the exceptional POV the array type is int -> A, and in the Try[.] POV the array type is int -> Try [ A ].

I was talking about the mechanism for array indexing. In both cases, indexing is function application. So the choice of error representation is orthogonal. This is even more evidence that we should not use a different operator for array indexing as Rust does alas.

OK I can agree with that, I think I was taking what you wrote as a wider endorsement of Scala's approach than what you intended.
What about '{}'? It's a nice pair of opening/closing characters.