www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Range Construction Pattern

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
Assumed I have the following code

     SysTime[] times;
     const n = 3;
     foreach (i; 0..n) times ~= Clock.currTime;

is there a simpler, perhaps functional, higher order pattern with 
which to achieve the same goal?
Feb 22 2014
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Saturday, 22 February 2014 at 12:29:11 UTC, Nordlöw wrote:
 Assumed I have the following code

     SysTime[] times;
     const n = 3;
     foreach (i; 0..n) times ~= Clock.currTime;

 is there a simpler, perhaps functional, higher order pattern 
 with which to achieve the same goal?
What's Clock.currTime exactly, a function? -- times = iota(3).map!(x => Clock.currTime).array; --
Feb 22 2014
next sibling parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Saturday, 22 February 2014 at 12:40:42 UTC, Tobias Pankrath 
wrote:
 On Saturday, 22 February 2014 at 12:29:11 UTC, Nordlöw wrote:
 Assumed I have the following code

    SysTime[] times;
    const n = 3;
    foreach (i; 0..n) times ~= Clock.currTime;

 is there a simpler, perhaps functional, higher order pattern 
 with which to achieve the same goal?
What's Clock.currTime exactly, a function? -- times = iota(3).map!(x => Clock.currTime).array; --
Great! See also: https://stackoverflow.com/questions/21954381/range-construction-pattern/21954416?noredirect=1#21954416
Feb 22 2014
parent "Tobias Pankrath" <tobias pankrath.net> writes:
 Great!

 See also: 
 https://stackoverflow.com/questions/21954381/range-construction-pattern/21954416?noredirect=1#21954416
I don't think that 'create' is a good name for a function, that basically lazily evaluates another function foo n times. Maybe std.range.repeat should have an overload that takes an alias to a callable, so you don't need this rather awkward use of iota.
Feb 22 2014
prev sibling parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
 times = iota(3).map!(x => Clock.currTime).array;
 --
Ok here's my try so far: auto create(alias fun)(size_t n) { import std.range: iota, map; return n.iota.map!(n => fun); } Now what remains is to retstrict create to only take a fun with *no* input arguments and a non-void return. How do I do that?
Feb 22 2014
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
 Now what remains is to retstrict create to only take a fun with *no*
input arguments and a non-void return.
 How do I do that?
With a template contraint. Not tested: import std.traits: isCallable, ParameterTypeTuple, ReturnType; auto create(alias fun)(size_t n) if (isCallable!fun && ParameterTypeTuple!(fun).length == 0 && !is(ReturnType!fun == void)) { import std.range: iota, map; return n.iota.map!(n => fun); }
Feb 22 2014
parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Saturday, 22 February 2014 at 14:03:11 UTC, Philippe Sigaud 
wrote:
 Now what remains is to retstrict create to only take a fun 
 with *no*
input arguments and a non-void return.
 How do I do that?
With a template contraint. Not tested: import std.traits: isCallable, ParameterTypeTuple, ReturnType; auto create(alias fun)(size_t n) if (isCallable!fun && ParameterTypeTuple!(fun).length == 0 && !is(ReturnType!fun == void)) { import std.range: iota, map; return n.iota.map!(n => fun); }
Your solution with ParameterTypeTuple!(fun).length == 0 doesn't work here because currTime takes a defaulted argument. I believe we need a new std.trait, say arityMin, for this. Any ideas on how to implement that? Perhaps using __traits(compiles...? See also my update at: https://stackoverflow.com/questions/21954381/range-construction-pattern/21954416?noredirect=1#21954416
Feb 22 2014
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
 I believe we need a new std.trait, say arityMin, for this.
 Any ideas on how to implement that? Perhaps using 
 __traits(compiles...?

 See also my update at:
 https://stackoverflow.com/questions/21954381/range-construction-pattern/21954416?noredirect=1#21954416
In the meantime you can use an is-expression: -- int foo() { return 12; } void bar() { } void baz(int x) { } void main() { pragma(msg, is(typeof(foo()) == void)); pragma(msg, is(typeof(bar()) == void)); pragma(msg, is(typeof(baz()) == void)); } -- You can check if arbitrary code compiles with the "if-typeof-delegate-trick": -- static if(is(typeof({ <code>})))) { // code compiles } --
Feb 22 2014
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
 You can check if arbitrary code compiles with the
"if-typeof-delegate-trick":
 --
 static if(is(typeof({ <code>}))))
 {
 // code compiles
 }
 --
Or with __traits(compiles, <code>), which better documents the intent.
Feb 22 2014
parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
My try so far:

import std.traits: isCallable, ReturnType, arity, 
ParameterTypeTuple;

enum arityMin0(alias fun) = __traits(compiles, fun()); // new 
syntax in 2.064

auto repeat(alias fun)(size_t n) if (isCallable!fun &&
                                      arityMin0!fun &&
                                      !is(ReturnType!fun == void))
{
     import std.range: iota, map;
     return n.iota.map!(n => fun);
}
Feb 22 2014
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
per.nordlow:
 My try so far:

 import std.traits: isCallable, ReturnType, arity, ParameterTypeTuple;

 enum arityMin0(alias fun) = __traits(compiles, fun()); // new syntax in
2.064
 auto repeat(alias fun)(size_t n) if (isCallable!fun &&
                                      arityMin0!fun &&

                                      !is(ReturnType!fun == void))
 {
     import std.range: iota, map;
     return n.iota.map!(n => fun);
 }
For a nullary function, this solution is certainly OK: short and understandable. I found a way to parse an entire function param list, including default args, but I don't remember right now how I did that. Maybe by parsing 'fun.stringof' Maybe this exists in Phobos now? btw, I'd call this template 'apply', because repeat already exists in Phobos with a different use.
Feb 22 2014
parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
 btw, I'd call this template 'apply', because repeat already 
 exists in
 Phobos with a different use.
Good idea! I'll rename it. I have a pile of extensions to std.algorithm, std.traits, std.numeric, I'll pull some day when I get the time... /Per
Feb 22 2014
parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
 I have a pile of extensions to std.algorithm, std.traits, 
 std.numeric, I'll pull some day when I get the time...
I mean push...
Feb 22 2014