News for hackers. Stuff that matters.
Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Tuesday December 03, 2024 @11:24AM (#42307894)
The argument you make about literature is one I have made before, but I don't think it applies here. To me, languages with clean syntax aren't just removing things arbitrarily. They remove things that aren't needed or they otherwise have large amounts of consistency.

Let's look at three implementations of a doubling function in modern languages where at least two of them are considered "clean" syntaxes.

F#:

    let double x =
        2 * x
Python:

    def double(x: int) -> int:
        return 2 * x
Rust:

    fn double(x: i32) -> i32 {
        return 2 * x;
    }
Tying back to my original point, are the brackets, annotations, semicolons, and return really needed? From my perspective, the answer is no. These are the simplest functions you can have as well. The differences get multiplied over a large codebase.

Are people here really making the argument that F# and MLs don't have clean syntax? All three of these functions have the same IDE behavior in terms of types being showcased in the IDE and also in the type-checking processes, with F# and Rust's type-checking happening at the compiler level and Python's happening with MyPy. People might argue that I left off type annotations for F#, and that's true, but I did so because they aren't required for F# to compile and have the same IDE features like the other languages. Even if I did, it would look like:

F# with type annotations:

    let double (x: int) : int =
        2 * x
which is still cleaner.
Re:8 months of OCaml after 8 years of Haskell in production ... by steveklabnik on Tuesday December 03, 2024 @12:05PM (#42308430)
Idiomatic Rust would look like this:

    fn double(x: i32) -> i32 {
        2 * x
    }
The reason Rust requires types here is because global inference is computationally expensive and causes spooky action at a distance. The only real difference between your F# and this is the braces, which I do personally think makes code easier to read.

Of course there’s more overhead in smaller functions. I’d never write this code in Rust. I’d either inline it, or use a closure, which does allow for inference, and dropping the braces given that this is a one liner:

    |x| 2 * x
Different needs for different things.
Re:8 months of OCaml after 8 years of Haskell in production ... by itishappy on Tuesday December 03, 2024 @12:24PM (#42308638)

    #  Rust
    let double = |x| 2 * x;
    double(3);

    // F#
    let double = (*) 2
    double 3

    -- Haskell
    let double = (*2)       
    double 3

    #  Python
    double = lambda x: 2 * x
    double(3)
Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Tuesday December 03, 2024 @01:22PM (#42309365)
If I am understanding that |x| 2 * x in Rust is an anonymous function, another F# equivalent is fun x -> 2 * x.
Re:8 months of OCaml after 8 years of Haskell in production ... by neonsunset on Tuesday December 03, 2024 @01:38PM (#42309596)
The Haskell and F# examples above use partial application.

This also works:

  let zeroCount = numbers |> Seq.filter ((=) 0) |> Seq.length
Re:8 months of OCaml after 8 years of Haskell in production ... by steveklabnik on Tuesday December 03, 2024 @06:21PM (#42312810)
It's a closure, not just an anonymous function, though it of course has an empty environment so it's not a significant difference in this case. Rust doesn't have syntax for anonymous functions, only closures.
Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Tuesday December 03, 2024 @01:19PM (#42309337)
I thought that the Rust playground was requiring me to use return, but I was mistaken. However, it actually lends to my original point though because I would wager that dropping the return was part of the influence of ML on the beginnings of Rust.
Re:8 months of OCaml after 8 years of Haskell in production ... by steveklabnik on Tuesday December 03, 2024 @06:20PM (#42312804)
Expression orientation certainly comes from that general space, for sure.
Re:8 months of OCaml after 8 years of Haskell in production ... by IshKebab on Tuesday December 03, 2024 @02:14PM (#42310048)
> Tying back to my original point, are the brackets, annotations, semicolons, and return really needed? From my perspective, the answer is no. These are the simplest functions you can have as well. The differences get multiplied over a large codebase.

The answer is no for this trivial function. As your code goes beyond this it gets harder for humans to parse and so the syntax becomes more necessary.

My earlier analogy is pretty perfect here actually. Do you really need spaces in "thank you"? No clearly not. Does that mean you shouldn't use spaces at all?

> Are people here really making the argument that F# and MLs don't have clean syntax?

No. You are literally replying to a comment where I agreed that it is "clean".