c3c icon indicating copy to clipboard operation
c3c copied to clipboard

Support splat for varargs

Open ygorpontelo opened this issue 1 year ago • 1 comments

In the case of the string::tformat function, it accepts a variable number of arguments to pass to the format string. Would be nice to be able to unpack an array when calling it, for example:

String[] parts = {"one", "two"};
String result = string::tformat("%s %s", ...parts);

Currently, i get this error when trying: Error: Splat may not be used with raw varargs. Trying to cast the parts array to any[] also doesn't seem to work.

ygorpontelo avatar Aug 12 '24 12:08 ygorpontelo

This is correct, as the compiler currently works but as an enhancement, this could be made to work in the general case, which will also increase the usefulness of the splat.

lerno avatar Aug 12 '24 14:08 lerno

This should be completely supported now.

lerno avatar Sep 10 '24 22:09 lerno

This should be completely supported now.

Sorry,no,it doesn't work with the latest c3c.Error: Splat may not be used with raw varargs if the length is not known.

LukyGuyLucky avatar Sep 18 '24 01:09 LukyGuyLucky

Just tested this, got the same error as LukyGuyLucky. The length should be know since i was using a fixed array, unless that is not the length it is referring to.

ygorpontelo avatar Sep 18 '24 07:09 ygorpontelo

module test;
extern fn void test(...);

fn void main()
{
	int[2] y;
	test(...y);
}

This fails?

lerno avatar Sep 18 '24 08:09 lerno

If you do:

extern fn void test(...);

fn void main()
{
	int[] y = { 1, 2 };
	test(...y);
}

Then this will fail, as you are splatting a runtime slice into a raw vararg.

However, this will succeed:

extern fn void test(...);

fn void main()
{
	int[] y = { 1, 2 };
	test(...y[:2]);
}

Because then the compiler will know the length.

lerno avatar Sep 18 '24 08:09 lerno

I thought int[] y = {1, 2} was the same as int[2] y = {1,2} just a different notation. Is that distinction useful? Feels like a pitfall to me.

ygorpontelo avatar Sep 18 '24 08:09 ygorpontelo

int[*] y = { 1, 2 } is the same as int[2] y = { 1, 2 }. int[] y = { 1, 2 } creates a slice, the former two are int[2]

lerno avatar Sep 18 '24 08:09 lerno

I've improved the error message now though, and enabled:

fn void test2(int a, int b) { }
fn void main()
{
  int[2] x = { 1, 2 };
  test2(...x);
}

lerno avatar Sep 18 '24 08:09 lerno

Didn't know about the [*] notation. With the new message and the improvement above this looks pretty solid, i'm eager to test it.

ygorpontelo avatar Sep 18 '24 09:09 ygorpontelo

@lerno Can confirm in the latest that this is working:

fn void test2(int a, int b) {
  io::printfn("a = %s, b = %s", a, b); // a = 5, b = 22
}

fn void main()
{
  int[*] x = { 5, 22 };
  test2(...x);
}

Adding three values errors correctly: Error: This argument would exceed the number of parameters, did you add too many arguments?

Adding one value errors correctly: Expected 1 more argument after this one, did you forget it?

Caleb-rg avatar Sep 25 '24 15:09 Caleb-rg

Thank you!

lerno avatar Sep 25 '24 19:09 lerno