News for hackers. Stuff that matters.
Re:Dave Herman’s contributions to Rust by willtim on Monday May 03, 2021 @09:04AM (#27024519)
In Rust, a function definition left-hand-side looks like an annotated pattern, e.g.

foo(x : int)

Therefore, one would expect to annotate the return type as,

foo(x : int) : string

Since the pattern is showing foo applied to x. The Rust syntax is actually confusing for both Haskell/ML programmers (where the arrow comes from) and mainstream programmers. It's too small an issue to change now though.

Rust's support for proper "algebraic data types" is very good and gives it an advantage over languages like C++. However there are some small surprises, such as forcing all enum constructors/fields to be public (one must therefore wrap it to make an abstract data type).

Every language has its warts and these are particularly minor ones.

Re:Dave Herman’s contributions to Rust by devit on Monday May 03, 2021 @09:17AM (#27024649)
That would imply that "foo(x: int)" is a string rather than a function.

Haskell doesn't use that notation either, it uses -> both for the parameter list and for the return type, and separates argument names (arguably, these are poor choices, since currying is not an efficient CPU-native operation and not intuitive so distinguishing between multiple arguments and returning closures is useful, and argument names are useful for documentation).

Re:Dave Herman’s contributions to Rust by willtim on Monday May 03, 2021 @09:34AM (#27024878)
> That would imply that "foo(x: int)" is a string rather than a function

But foo(x : int) is a string! It literally reads "foo applied to x". In the function definition, it appears to be used as a left-hand-side pattern which is "matched". The definition is written as if to say, whenever the term foo(x) is encountered, use this definition here. At least, that was my expectation.

> Haskell doesn't use that notation either

OCaml does and Haskell once had a proposal to add it. Haskell type signatures are normally written separately, but it does support annotating patterns with the right extensions.

Re:Dave Herman’s contributions to Rust by gpm on Monday May 03, 2021 @11:10AM (#27026077)
No, foo(x: int) is not a string, it's not even an expression, it's not even an AST node. It's a fragment of the larger ast node

    fn foo(x: int) -> ReturnType {
        body
    }
The ast here splits into

    Function {
        name: foo
        signature: (x: int) -> ReturnType
        body: body
    }
I.e. the arrow binary op binds more tightly than the adjacency between foo and x: int. And the type of foo is a function, not a string.

A "better" way to write this (in that it breaks down the syntax into the order it is best understood) might be

    static foo: (Int -> ReturnType) = {
        let x = arg0;
        body
    }
Or to put it another way. Reading foo(x: int) as "foo applied to x" in this case is a mistake, because that's now how things bind. You should read that "foo is a (function that takes Int to String)". It's a syntactic coincidence that foo and x are beside eachother, nothing more.
Re:Dave Herman’s contributions to Rust by willtim on Monday May 03, 2021 @11:36AM (#27026427)
That's a nice explanation of what's going on. My point remains that I found the syntax confusing though.
Re:Dave Herman’s contributions to Rust by gpm on Monday May 03, 2021 @11:47AM (#27026576)
Ya, I'm not really going to defend the current syntax past "function syntax is hard".

It's mixing up assigning a global variable, specifying that variables type, and destructuring an argument list into individual arguments, in one line. I've played at making my own language, and this is one part that I've never been satisfied with.

Personally I'd probably at least go with a `foo = <anonymous function>` syntax to split out the assigning part. But that's spending "strangeness budget" because that's not how C/Python/Java do it, and I can understand the decision to not spend that budget here...

Re:Dave Herman’s contributions to Rust by ZoomZoomZoom on Monday May 03, 2021 @10:20AM (#27025404)
> But foo(x : int) is a string!

Can you say so decisively for a language with first-class functions?

Re:Dave Herman’s contributions to Rust by willtim on Monday May 03, 2021 @11:34AM (#27026402)
You are quoting me out of context. In many languages, the term and/or pattern foo(x : int) is a string, if foo : int -> string.
Re:Dave Herman’s contributions to Rust by kaba0 on Monday May 03, 2021 @10:01AM (#27025172)
Just a nitpick, but currying is a language detail, one can potentially create an efficient implementation with or without them.
Re:Dave Herman’s contributions to Rust by willtim on Monday May 03, 2021 @10:07AM (#27025255)
Yes and of course Haskell is quite capable of supporting uncurried functions too, e.g.

foo :: (Int, Int) -> Int

foo (x, y) = ...

Re:Dave Herman’s contributions to Rust by valenterry on Monday May 03, 2021 @09:34AM (#27024872)
I don't think that would be the implication, because we are in the context of a function. Otherwise, we should also not write foo(x: int) but foo: int -> ?
Re:Dave Herman’s contributions to Rust by ModernMech on Monday May 03, 2021 @09:38AM (#27024920)
I wouldn't say this is a wart or confusing (to me at least). As someone who uses Haskell, C++, and Rust regularly, I just accept that each language has its own syntax. It's true that Rust borrows ideas from many languages, but I view Rust's syntax as its own thing, and the meaning of the symbols are what they are. It doesn't have to do things the C++ way or the Haskell way. It does things the Rust way, and that's not a wart.
Re:Dave Herman’s contributions to Rust by willtim on Monday May 03, 2021 @09:45AM (#27024988)
It did confuse me when I first saw it, but yes, it is not really a significant issue.
Re:Dave Herman’s contributions to Rust by jeltz on Monday May 03, 2021 @11:20AM (#27026223)
Having used both Haskell and main stream programming languages I did not at all think that was confusing. The type of "fn foo(x: int) -> string" is quite obviously "fn(x: int) -> string" for people coming from languages like C. I do not see how a colon would make anything more clear. Imagine the function "fn bar(x: fn(x: int) -> string)", would that be more clear with a colon?

On the other hand the enum thing is certainly surprising.

Re:Dave Herman’s contributions to Rust by willtim on Monday May 03, 2021 @11:57AM (#27026705)
> Imagine the function "fn bar(x: fn(x: int) -> string)", would that be more clear with a colon?

In your example, why bother naming the inner "x" variable for the function param? It cannot be used on the right-hand-side (definition of "bar"). For that reason, the notation is not exactly "clear". In OCaml the annotation would be:

bar( x : int -> string )

Re:Dave Herman’s contributions to Rust by east2west on Monday May 03, 2021 @01:11PM (#27027754)
In Rust you can write ```f: fn(i32) -> i32```.

Ocaml's syntax is more consistent, I agree, but its colon operator has different precedence than in Rust, so I am not sure its rational applies to Rust.

Re:Dave Herman’s contributions to Rust by ape4 on Monday May 03, 2021 @10:39AM (#27025656)
I typed `foo(x : int) : string` when I was starting and there was an error message telling me to use `-> string` so many people expect this syntax.
Re:Dave Herman’s contributions to Rust by uryga on Monday May 03, 2021 @10:11AM (#27025306)
> one would expect to annotate the return type as

> foo(x : int) : string

> since the pattern is showing foo applied to x.

kind of like the C/C++ "declaration mirrors use" thing, i.e.

  int *foo;
which means

"the result of dereferencing `foo` is of type `int`"

which is not the same as saying

  foo : Ptr<int>;
because in the former, you're kind of describing what `foo` is a without actually saying it, if that makes sense.

i find that way of specifying types counterintuitive in both C/C++ and MLs.

Re:Dave Herman’s contributions to Rust by the__alchemist on Monday May 03, 2021 @09:34AM (#27024876)
FYSA, The Rust approach is the same way it's done in Python.
Re:Dave Herman’s contributions to Rust by willtim on Monday May 03, 2021 @09:42AM (#27024958)
Well the Python community is hardly an authoritative figure on static typing :)
Re:Dave Herman’s contributions to Rust by acdha on Monday May 03, 2021 @10:47AM (#27025735)
This is true but Python has a user community which is several orders of magnitude broader, which confuses the issue a bit. These days if I was designing a language I'd probably ask “How would I explain this to someone who learned JavaScript/Python?” since even if you have great reasons for doing things differently it's a pretty reasonable way to predict sources of confusion for newcomers.