Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I would say syntax is everything. What's the difference between python and Haskell without syntax?


Lazy vs strict semantics are completely orthogonal to the syntax [0]. (foo a b c) looks the same in a lazy language as it does in a strict language but oh boy are the results surprisingly different if you don't already know what you're in for.

0. Though some would argue that making them completely orthogonal to the point where the user can't tell the difference is a horrible design decision.


> Lazy vs strict semantics are completely orthogonal to the syntax [0]

Alternatively, the syntax in Haskell just lends itself to lazy evaluation, and requires explicit annotation syntax to be strict. Contrasted with Python, which has a syntax that makes strict evaluation an easier default to express.

If all languages can express, with some effort, the same exact semantics as any other language, then the only difference is syntax.


I'd submit the key difference in Haskell syntax is actually currying, not laziness. Haskell syntax privileges currying, and an executed function is just a curried function that has all of its parameters. By contrast, currying in languages with Algol-descended syntax always requires more rigamarole. It's possible, of course, in a lot of them, but it's harder than just a function call missing some of its arguments.


> By contrast, currying in languages with Algol-descended syntax always requires more rigamarole. It's possible, of course, in a lot of them, but it's harder than just a function call missing some of its arguments.

Really? Given a Python function

    def divide_by(a, b):
        return a / b
What would be so hard about

    divided_by_2 = divide_by(, 2)
    divide_5 = divide_by(5, )
Or, in Rust:

    fn divide_by(a: f32, b: f32) -> f32 {
        a / b
    }
    // ...
    let divide_by_2 = divide_by(, 2.0);
    let divide_5 = divide_by(5.0, );
I can't immediately see any major problems with this. It's basically a closure, after all:

    let divide_by_2 = |a| divide_by(a, 2.0);


"What would be so hard about divided_by_2 = divide_by(, 2)"

Well, first of all, it doesn't work right now, which is a problem for what I was trying to say.

Secondly, if you want to curry things, you'll end up with

    four_arg_func(1, 2)(3)(4)
at a bare minimum as a "curried application", where in Haskell it's just

    four_arg_func 1 2 3 4
Several Algol languages have other issues, such as dealing with optional arguments: in Python!curryable, is the result of

    def f(a, b, c = 10):
        return a + b + c

    f(1, 2)
a function that accepts one more parameter for c, or the number 13? (Even in a dynamic language you ought to think twice before trying to return some sort of "quantum superposition" of those two things!) You'll need to add some syntax that will specify the answer to that question, and now Python!curryable is getting away from just "incompletely applying the function" as it is in Haskell, but now a Thing you have to Do. (Probably by calling https://docs.python.org/2/library/functools.html#functools.p... .)

Haskell hacks that away by making it so functions take a fixed number of parameters, in a fixed order, and there is no such thing as default parameters to a function. A non-Haskell programmer may feel this is not a trade worth making.

Your closure at the end is what it tends to really look like. You'll note that most non-functional code doesn't really do that sort of thing very often, unless you're unlucky enough to stumble across a codebase written by someone trying to write Haskell-in-Python or something.


My point is that the "it's harder" is why syntax is the differentiator.

The idea that syntax isn't a huge differentiator for languages is insane to me. Yes, small syntactic changes like "fun" vs "fn" may not matter overall, but obviously people choose languages based on what they can easily express by typing sourcecode.

Arguably, the difference between await syntaxes is closer to "fn vs fun" than "lazy vs strict", but I think that there's a lot of context that pushes it closer to the latter (we're talking about how a fundamental control flow primitive is implemented, and this will impact future control flow primitives).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: