digitalmars.D.learn - Lazy variadic not working, any alternatives?
- Tofu Ninja (25/25) May 25 2015 So I was writing a simple parser and I wanted a functionality
- Tofu Ninja (61/61) May 25 2015 On Tuesday, 26 May 2015 at 05:22:26 UTC, Tofu Ninja wrote:
- Tofu Ninja (3/7) May 25 2015 I guess it stems from the fact that its "lazy (bool[])"
- Steven Schveighoffer (6/13) May 26 2015 Lazy variadic functions are clearly defined here:
- John Colvin (18/43) May 25 2015 Something like this appears to work:
- Tofu Ninja (3/20) May 25 2015 Hmmm.... this does seem to work. Does this essentially expand out
- John Colvin (9/32) May 26 2015 Apparently yes, which surprised me. Storage classes and
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 25 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 25 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 25 2015
On 5/25/15 11:53 PM, Tofu Ninja wrote:On Tuesday, 26 May 2015 at 05:43:59 UTC, Tofu Ninja wrote: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 ...) -SteveOn 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 25 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 25 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: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.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