www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Lazy Literal Range: Stooid late-nite idea?

reply "Nick Sabalausky" <a a.a> writes:
Suppose you want to search through a range (yea, really hypothetical so 
far... ;) )

    auto x = ["foo", "bar", "bat", "meow"].find("bar");
    assert(x.front == "bar");

Great, right? But what about this?:

    auto x = [runtimeExpressionA, runtimeExprB, runtimeExprC, 
etc].find(blah);

Doable, but then *all* those expressions have to be evaluated even if the 
desired element is one of the first few. What about a range literal, nice 
and easy like array, but lazily evaluated? I'm not suggesting anything built 
into the language, of course, just an easily instantiated library type.

Good idea? Not hard to make? Already exists? Usefulness likely killed by 
delegate overhead?
Oct 08 2011
parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Sun, 09 Oct 2011 06:06:21 +0300, Nick Sabalausky <a a.a> wrote:

 Great, right? But what about this?:

     auto x = [runtimeExpressionA, runtimeExprB, runtimeExprC,
 etc].find(blah);

With the anonymous delegate literal syntax suggested by Andrei a while ago, you should be able to write this as: auto x = [() => runtimeExpressionA, () => runtimeExprB, () => runtimeExprC, () => etc].find(blah); I guess it looks quirky with an empty parameter list, but it's shorter than writing {return runtimeExpressionA;}, {return runtimeExpressionB;} etc. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Oct 08 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-09 08:33, Vladimir Panteleev wrote:
 On Sun, 09 Oct 2011 06:06:21 +0300, Nick Sabalausky <a a.a> wrote:

 Great, right? But what about this?:

 auto x = [runtimeExpressionA, runtimeExprB, runtimeExprC,
 etc].find(blah);

With the anonymous delegate literal syntax suggested by Andrei a while ago, you should be able to write this as: auto x = [() => runtimeExpressionA, () => runtimeExprB, () => runtimeExprC, () => etc].find(blah); I guess it looks quirky with an empty parameter list, but it's shorter than writing {return runtimeExpressionA;}, {return runtimeExpressionB;} etc.

Or wrap it in a function taking a list of lazy parameters: http://www.d-programming-language.org/function.html#parameters auto x = lazyRange(runtimeExpressionA, runtimeExprB, runtimeExprC); -- /Jacob Carlborg
Oct 09 2011
parent reply Lutger Blijdestijn <lutger.blijdestijn gmail.com> writes:
Jacob Carlborg wrote:

 On 2011-10-09 08:33, Vladimir Panteleev wrote:
 On Sun, 09 Oct 2011 06:06:21 +0300, Nick Sabalausky <a a.a> wrote:

 Great, right? But what about this?:

 auto x = [runtimeExpressionA, runtimeExprB, runtimeExprC,
 etc].find(blah);

With the anonymous delegate literal syntax suggested by Andrei a while ago, you should be able to write this as: auto x = [() => runtimeExpressionA, () => runtimeExprB, () => runtimeExprC, () => etc].find(blah); I guess it looks quirky with an empty parameter list, but it's shorter than writing {return runtimeExpressionA;}, {return runtimeExpressionB;} etc.

Or wrap it in a function taking a list of lazy parameters: http://www.d-programming-language.org/function.html#parameters auto x = lazyRange(runtimeExpressionA, runtimeExprB, runtimeExprC);

typesafe variadics with delegates also allow for this syntax, though not with type inference. I hacked this together: struct LazyRange(T) { import std.array; this(T delegate()[] input...) { _input = input; } property bool empty() const { return std.array.empty(_input); } void popFront() { std.array.popFront(_input); _isCached = false; } property T front() { if (_isCached) return _front; _front = std.array.front(_input)(); _isCached = true; return _front; } private: T _front; bool _isCached = false; T delegate()[] _input; } unittest { import std.algorithm; auto stuff = LazyRange!string("foo", "foo" ~ "bar", { assert(false); return "bat"; }(), "meow"); assert(find(stuff,"foobar").front == "foobar"); }
Oct 09 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-10-09 13:43, Lutger Blijdestijn wrote:
 Jacob Carlborg wrote:

 On 2011-10-09 08:33, Vladimir Panteleev wrote:
 On Sun, 09 Oct 2011 06:06:21 +0300, Nick Sabalausky<a a.a>  wrote:

 Great, right? But what about this?:

 auto x = [runtimeExpressionA, runtimeExprB, runtimeExprC,
 etc].find(blah);

With the anonymous delegate literal syntax suggested by Andrei a while ago, you should be able to write this as: auto x = [() => runtimeExpressionA, () => runtimeExprB, () => runtimeExprC, () => etc].find(blah); I guess it looks quirky with an empty parameter list, but it's shorter than writing {return runtimeExpressionA;}, {return runtimeExpressionB;} etc.

Or wrap it in a function taking a list of lazy parameters: http://www.d-programming-language.org/function.html#parameters auto x = lazyRange(runtimeExpressionA, runtimeExprB, runtimeExprC);

typesafe variadics with delegates also allow for this syntax, though not with type inference. I hacked this together: struct LazyRange(T) { import std.array; this(T delegate()[] input...) { _input = input; } property bool empty() const { return std.array.empty(_input); } void popFront() { std.array.popFront(_input); _isCached = false; } property T front() { if (_isCached) return _front; _front = std.array.front(_input)(); _isCached = true; return _front; } private: T _front; bool _isCached = false; T delegate()[] _input; } unittest { import std.algorithm; auto stuff = LazyRange!string("foo", "foo" ~ "bar", { assert(false); return "bat"; }(), "meow"); assert(find(stuff,"foobar").front == "foobar"); }

Interesting, I didn't know you could do that with a delegate without declaring a lazy parameter. This works with D1: void lazyRange (T) (lazy T[] e ...) { foreach (a ; e) println(a); } void main () { lazyRange(3, 4); } But compiling the same code with D2 results in this error: Error: escaping reference to local __arrayArg1344 -- /Jacob Carlborg
Oct 09 2011