3

I'm playing around with Ceylon and I'm trying to create an alias for a tuple. The following do not work:

class MyPair(Integer i, Float f) => [i, f];
class MyPair(Integer i, Float f) => [Integer, Float](i, f);
class MyPair(Integer i, Float f) => 
        Tuple<Integer|Float, Integer, Tuple<Float, Float, Empty>>(i, [f]);
class MyPair(Integer i, Float f) => 
        Tuple<Integer|Float, Integer, Tuple<Integer|Float, Float, Empty>>(i, [f]);
class MyPair(Integer i, Float f) => 
        Tuple<Integer|Float,Integer,Tuple<Float,Float,Empty>>(i, Tuple<Float,Float,Empty>(f, []));

The error I get on the first two revolves around the use of brackets:

Incorrect syntax: missing statement-ending ; at [ expecting statement-ending ;

There are two separate errors on the second:

Some variation of

Alias parameter distance must be assignable to corresponding class parameter rest: Integer is not assignable to [Integer]

on class MyPair and

Argument must be a parameter reference to distance

on f, [f], or the tuple construction.

Is there a way to do this?

Jeffrey
  • 44,417
  • 8
  • 90
  • 141

3 Answers3

4

Yeah, the instantiation expression on the RHS of the => in a class alias declaration is currently extremely restricted, not by design, but just because it will take some extra work to implement full support for arbitrary instantiation expressions in the compiler backends.

But what I would actually do for now would be to use a regular type alias, like this:

alias MyPair => [Integer,Float];

And use it like this:

MyPair pair = [1, 1.0];

I think that's actually even cleaner than using a class alias.

HTH.

Gavin King
  • 3,182
  • 1
  • 13
  • 11
  • Aha, didn't know that was possible. My understanding of [the tour](http://ceylon-lang.org/documentation/1.1/tour/typeinference/) led me to believe that a regular `alias` can only be used with intersection and union types. – Jeffrey Aug 13 '15 at 03:01
  • You can use `alias` with any legal type, actually. The difference is that you can't use an `alias` everywhere you can use a `class` alias—in particular, you can't use it in an `extends` clause, and you can't use it in an instantiation expression. But since in this case: `Tuple` is `final` anyway, so that's not actually an additional restriction, and you can't really improve on the nice `[x,y]` syntax for instantiation either. – Gavin King Aug 14 '15 at 08:28
2

After tinkering around a bit I came across

class MyPair(Integer i, [Float] f) => 
        Tuple<Integer|Float, Integer, Tuple<Float, Float, Empty>>(i, f);

which works.

Jeffrey
  • 44,417
  • 8
  • 90
  • 141
2

Can't do much better than your solution, but you can at least use a shortcut for the Rest type parameter:

class Pair([Integer i, [Float] f]) => Tuple<Integer|Float, Integer, [Float]>(i, f);

You're limited here because the parameter types of your class alias must match the parameter types of the class that you're aliasing. If I'm interpreting the spec correctly:

Note: currently the compiler imposes a restriction that the callable type of the aliased class must be assignable to the callable type of the class alias. This restriction will be removed in future.

then this might work in subsequent releases:

class Pair(Integer i, Float f) => Tuple<Integer|Float, Integer, [Float]>(i, [f]);

or maybe even:

class Pair(Integer i, Float f) => [i, f];

Then again, if your aim is to destructure a tuple, Ceylon 1.2 will let you do that directly:

value [i, f] = [2, 0.5];
gdejohn
  • 7,451
  • 1
  • 33
  • 49
  • Thank you! My actual goal was to do something like `class Pair(shared Integer i, shared Float f) => [i, f]` to alias the elements of the pair to a different name. It looks like the only way to achieve that is with a fully fledged class. I understand that feature would be hard to implement in general (what happens if there's an attribute in tuple named `i` with a different type?), but I was hoping for a shortcut. – Jeffrey Aug 12 '15 at 16:40
  • @Jeffrey Are you sure destructuring isn't what you're looking for? Maybe you could update your question with an example of how you'd be using your `Pair` class. – gdejohn Aug 12 '15 at 17:43
  • Destructuring would probably work just as well, except I'm still using 1.1. – Jeffrey Aug 12 '15 at 17:45
  • Well, something to look forward to then. – gdejohn Aug 12 '15 at 17:56