Thread overview
Lazy variadic not working, any alternatives?
May 26, 2015
Tofu Ninja
May 26, 2015
Tofu Ninja
May 26, 2015
Tofu Ninja
May 26, 2015
John Colvin
May 26, 2015
Tofu Ninja
May 26, 2015
John Colvin
May 26, 2015
So I was writing a simple parser and I wanted a functionality that was basically "try list of tokens in order and if any of them fail, rewind input".

I tried using a lazy variadic function:

bool tok_and(lazy bool[] terms ...)
{
	auto backup = getInputLocation();
	for(int i = 0; i < terms.length; i++)
	{
		if(terms[i] == false)
		{
			rewind(backup);
			return false;
		}
	}
	return true;
}

But this does not work because of BUG9110
https://issues.dlang.org/show_bug.cgi?id=9110

Any one have an idea how to achieve similar functionality without a bunch of boilerplate at the call site? The lazy version would have been nice because it would have allowed for:

if(tok_and(ident(), equal(), expression())) {...}
else if(tok_and(some(), other(), grammar())) {...}
else ...


May 26, 2015
On Tuesday, 26 May 2015 at 05:22:26 UTC, Tofu Ninja wrote:
Actually the code seems to compile on 2.067.1 but definitely does not work as expected.

Another example of Lazy variadic to show how it works...

void main(string[] args)
{
	test(a(), b(), c());
}

bool a()
{
	writeln("a");
	return true;
}

bool b()
{
	writeln("b");
	return true;
}

bool c()
{
	writeln("c");
	return true;
}

void test(lazy bool[] c...)
{
	for(int i = 0; i < c.length; i++)
	{
		writeln("iteration: ", i);
		if(c[i]) writeln("success");
	}
}

prints...

a
b
c
iteration: 0
a
b
c
success
a
b
c
iteration: 1
a
b
c
success
a
b
c
iteration: 2
a
b
c
success
a
b
c

Though because it still runs in order, maybe I can still make this work...
May 26, 2015
On Tuesday, 26 May 2015 at 05:43:59 UTC, Tofu Ninja wrote:
> On Tuesday, 26 May 2015 at 05:22:26 UTC, Tofu Ninja wrote:
> Actually the code seems to compile on 2.067.1 but definitely does not work as expected.
> ...

I guess it stems from the fact that its "lazy (bool[])"
Wish I could do "(lazy bool)[]"
May 26, 2015
On Tuesday, 26 May 2015 at 05:22:26 UTC, Tofu Ninja wrote:
> So I was writing a simple parser and I wanted a functionality that was basically "try list of tokens in order and if any of them fail, rewind input".
>
> I tried using a lazy variadic function:
>
> bool tok_and(lazy bool[] terms ...)
> {
> 	auto backup = getInputLocation();
> 	for(int i = 0; i < terms.length; i++)
> 	{
> 		if(terms[i] == false)
> 		{
> 			rewind(backup);
> 			return false;
> 		}
> 	}
> 	return true;
> }
>
> But this does not work because of BUG9110
> https://issues.dlang.org/show_bug.cgi?id=9110
>
> Any one have an idea how to achieve similar functionality without a bunch of boilerplate at the call site? The lazy version would have been nice because it would have allowed for:
>
> if(tok_and(ident(), equal(), expression())) {...}
> else if(tok_and(some(), other(), grammar())) {...}
> else ...

Something like this appears to work:

import std.typetuple : allSatisfy;

enum implicityConvertibleToBool(T) = is(T : bool);

bool tok_and(Args...)(lazy Args terms)
if(allSatisfy!(implicitlyConvertibleToBool, Args))
{
	auto backup = getInputLocation();
	foreach(term; terms)
	{
		if(term == false)
		{
			rewind(backup);
			return false;
		}
	}
	return true;
}
May 26, 2015
On Tuesday, 26 May 2015 at 05:54:11 UTC, John Colvin wrote:
> Something like this appears to work:
>
> import std.typetuple : allSatisfy;
>
> enum implicityConvertibleToBool(T) = is(T : bool);
>
> bool tok_and(Args...)(lazy Args terms)
> if(allSatisfy!(implicitlyConvertibleToBool, Args))
> {
> 	auto backup = getInputLocation();
> 	foreach(term; terms)
> 	{
> 		if(term == false)
> 		{
> 			rewind(backup);
> 			return false;
> 		}
> 	}
> 	return true;
> }

Hmmm.... this does seem to work. Does this essentially expand out to tok_and(lazy bool arg1, lazy bool arg2, ...)?
May 26, 2015
On 5/25/15 11:53 PM, Tofu Ninja wrote:
> On Tuesday, 26 May 2015 at 05:43:59 UTC, Tofu Ninja wrote:
>> On Tuesday, 26 May 2015 at 05:22:26 UTC, Tofu Ninja wrote:
>> Actually the code seems to compile on 2.067.1 but definitely does not
>> work as expected.
>> ...
>
> I guess it stems from the fact that its "lazy (bool[])"
> Wish I could do "(lazy bool)[]"

Lazy variadic functions are clearly defined here: http://dlang.org/function.html

The correct way to do it is:

bool tok_and(bool delegate()[] terms ...)

-Steve
May 26, 2015
On Tuesday, 26 May 2015 at 06:04:59 UTC, Tofu Ninja wrote:
> On Tuesday, 26 May 2015 at 05:54:11 UTC, John Colvin wrote:
>> Something like this appears to work:
>>
>> import std.typetuple : allSatisfy;
>>
>> enum implicityConvertibleToBool(T) = is(T : bool);
>>
>> bool tok_and(Args...)(lazy Args terms)
>> if(allSatisfy!(implicitlyConvertibleToBool, Args))
>> {
>> 	auto backup = getInputLocation();
>> 	foreach(term; terms)
>> 	{
>> 		if(term == false)
>> 		{
>> 			rewind(backup);
>> 			return false;
>> 		}
>> 	}
>> 	return true;
>> }
>
> Hmmm.... this does seem to work. Does this essentially expand out to tok_and(lazy bool arg1, lazy bool arg2, ...)?

Apparently yes, which surprised me. Storage classes and TypeTuples (or Arguments, as they are now) are a bit of a dark corner. E.g.

void foo(ref int, ref int);
alias A(T...) = T;
static assert(is(ParameterTypeTuple!foo == A!(ParameterTypeTuple!foo)));

That fails.