ceylon / ceylon-spec

DEPRECATED
Apache License 2.0
108 stars 34 forks source link

change sugar for `Callable`s #1397

Closed ghost closed 9 years ago

ghost commented 9 years ago

For me, this makes more sense than what is done currently:

(Integer, String) => Float f =
(Integer i, String s) => 0.0;

It also resembles the syntax for type functions, and works nicely with it:

function foo<Bar>(Baz b)(Qux q) => Quxx();
// Type: <Bar> => (Baz) => (Qux) => Quxx

Besides, the parameter lists are in the same order in the type of the function, as they are when calling the function!

gavinking commented 9 years ago

Currently the fat arrow has a very clear semantic: it means that the thing on the left is evaluated lazily. That's even true for a type function!

This proposal would break that, since in a function type nothing is evaluated lazily.

gavinking commented 9 years ago

Note that it's also inconsistent with the traditional C syntactic principle: "declaration follows use". In C, an array type is written int[][] not [][]=>int. And I think the second option would be a really ugly way to write array types (though I note that Go sorta goes down this path).

ghost commented 9 years ago

Why not make the type function thingies similar to the current Callable syntax, then?

Foo bar<Baz>(Qux q) => nothing;
Foo(Qux)<Baz> bar2 = bar;
gavinking commented 9 years ago

@Zambonifofex the syntax Foo(Qux)<Baz> looks to me like a type of a type function, not a definition of a type function.

ghost commented 9 years ago

That isn't wrong. Both bar and bar2 are type functions and have the same type, but bar2 is declared like an value, instead of like an function. Foo(Qux)<Bar> is the type of both.

gavinking commented 9 years ago

Nope, that's not the right way to look at it. That's like not seeing the difference between (Float x) => x and Float(Float).

A type function is really a function. Thus, we write it as <T> => T, using a similar syntax we use to write value functions.

ghost commented 9 years ago

Well, I'm confused. I have thought about this, and came to the conclusion that <Foo> => Bar means two different things.

Am I right in thinking like this?

gavinking commented 9 years ago

That's right, but you're not thinking meta enough. I'm saying Foo(Qux)<Bar> looks like the type of a type function at the next meta-level up.

ghost commented 9 years ago

So, you mean:

Foo<Bar> typefun = <Bar> => Baz;

Or, even better:

Foo typefun<Bar> => Baz;

Where Foo is the type of the type Baz...

ghost commented 9 years ago

By the way, @gavinking, would it not be better to not have it mean two different things? Maybe have a function that receives a type and "returns" another be represented as <Foo> => Bar, and the type of a function that receives a type and returns another as Bar<Foo>...

gavinking commented 9 years ago

I don't understand. You've lost me.

Look, I think you're not seeing this because you're writing everything with Foo, and Bar as opaque things whereas really Bar is an expression that involves Foo. There's just a huge difference there. The thing on the left of the fat arrow is always a parameter list, not a type!

When I have a generic function type like <T> => List<String>(List<T>), the stuff to the right of the fat arrow is an expression involving parameters declared on the right of the fat arrow.

If I have a plain function type String(Integer), String simply can't be an expression that involves Integer. Indeed, Integer isn't a parameter at all! So what sense would it make to write that as (Integer) => String?

ghost commented 9 years ago

No, I've realized this. What got me confused was the fact that <Foo> => Bar means two different things.

What I said is that I think <Foo> => Bar should be only a type function, and not a type by itself. And, have Foo<Bar> be the type of a function that receives a type and returns an object. For example:

function foo<Bar>()
given Bar<Baz>
{
    // ...
}

foo< <Baz>=>String >(); // Ok

<Baz>=>String err => nothing; // Error

String qux<Bar>() => "Hello";

String()<> quxx = qux; // Ok

Since I don't agree with this thread's suggestion anymore, and am now suggesting something else, I'll close this thread. @gavinking should I open another thread, should I reopen this one, or should I just leave this closed, and don't open anything?

gavinking commented 9 years ago

What I said is that I think <Foo> => Bar should be only a type function, and not a type by itself

Nononono!

That's like saying: I think (Float x) => x should be only a function, and not a value. That's the situation in languages without higher-order functions.

Likewise, in a language with higher-order generic types, we have functions that are types.

That's the whole conceptual model. It's not a weird wrinkle of the syntax; it's a correct representation of exactly what is going on here!