Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Argument Splats #47

Closed
trans opened this issue Sep 21, 2013 · 8 comments
Closed

Support for Argument Splats #47

trans opened this issue Sep 21, 2013 · 8 comments

Comments

@trans
Copy link

trans commented Sep 21, 2013

Seeing what Ruby code I can port to Crystal. I see that argument splats cause a compile error unexpected token: *

def initialize(*points)

Will support for these be coming?

@asterite
Copy link
Member

Yes, but not in the same way as Ruby.

The problem is, we need to know the number and type of arguments at compile time. For example

def foo(x, y)
  x + y
end

a = [1, 2, 3]
foo *a

This in Ruby gives wrong number of arguments at runtime, of course. But how can Crystal know that at compile time? (Crystal is not a dynamic language)

The answer is: this will not be possible in Crystal.

Instead, we will have a Tuple type. A tuple has a fixed size and each element has a (possible different) type. The syntax will probably be:

{1, "hello", 'a'} #=> Tuple(Int32, String, Char)

You can't add elements to a tuple and (most probably) you can't modify it: it's (most probably) immutable. Because of this the compiler can know the types and length of a tuple and you can use a splat to pass a tuple to a method. For example:

def foo(x, y)
  x + y
end

a = {1, 2}
foo *a # ok, a has length 2 and types Int32, Int32 so that compiles

b = {1, 2, "hello"}
foo *b # error, doesn't compile

Although this severly reduces the power of the programming language, it allows to pass along splat arguments:

def foo(*args)
  bar *args
end

Well... this is just an idea we have, it's not finished and we are still not sure about it. But for sure splats will never work with arrays types.

@trans
Copy link
Author

trans commented Sep 21, 2013

Let me see if I understand:

def foo(*a)
  a
end

x = foo(1,2,3)
p x  #=> {1,2,3}
p x.class  #=> Tuple

@asterite
Copy link
Member

Yes, exactly.

In fact, now that you mention it, doing that makes it unnecessary to have a special syntax for tuples.

def tuple(*args)
  args
end

x = tuple 1, 2, 3

This is also how it is done in the D programming language: http://dlang.org/tuple.html

template Tuple(E...)
{
    alias E Tuple;
}

auto tuple = Tuple!(1, 2 , 3);

It's also similar to the way you can create a Proc in Ruby:

def proc(&block)
  block
end

p = proc { ... }

Hacky :-P

@trans
Copy link
Author

trans commented Sep 22, 2013

👍 Awesome. Looking forward to putting them little tuples to work.

@asterite
Copy link
Member

asterite commented Aug 3, 2014

@trans I just pushed a couple of commits that implement this :-)

Since it's so new you might find bugs in it. Also, don't try to combine default values with splats, I'm sure it doesn't work. But, at least, we can do more things now.

Soon... named arguments :-D

@asterite
Copy link
Member

All of this, plus named arguments, work since version 0.4

@trans
Copy link
Author

trans commented Aug 11, 2014

Sweet!!! I'll start porting as soon.

@asterite
Copy link
Member

Just beware that splats aren't supported in initialize (I just checked it). I'll fix it soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants