Thread overview
[Issue 9550] New: Repeat!fun(size_t n)
Feb 20, 2013
Daniel Cousens
Feb 20, 2013
Daniel Cousens
February 20, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=9550

           Summary: Repeat!fun(size_t n)
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody@puremagic.com
        ReportedBy: daniel350@bigpond.com


--- Comment #0 from Daniel Cousens <daniel350@bigpond.com> 2013-02-19 23:45:50 PST ---
Unless I'm missing something, after several separate discussions on the D IRC, I could not find a way to run a function 'n' times lazily for a range without doing hackery's like this:

iota(100).map!(x => uniform(0, 76));

The use case is where you want to repeat an (impure) function n times lazily.
A possible example:

auto five_random_ints = take(recurrence!(uniform!int), 5)

or

auto five_random_ints = repeat!(uniform!int)(5);

If there is an idiomatic way to do this already that I am missing, sorry for taking up your time.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 20, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=9550


monarchdodra@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra@gmail.com


--- Comment #1 from monarchdodra@gmail.com 2013-02-20 00:16:07 PST ---
Isn't what you are asking for a special case of sequence that discards any and all input?

//----
int fun(T)(T/+Tuple!()+/, uint n)
{
    static int i;
    return ++++i;
}

void main()
{
    auto a = sequence!fun();
    writeln(a.take(10));
}
//----
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
//----

In this case "T" is a tuple containing the empty state, and n is the iteration count.

Apart from the fancy sig, it's what you are asking for.

Given that the signature of "fun" isn't specified yet, we could special case
sequence for sequences that have no initial state, to simply call fun(n) (as
well as be more efficient).

I think it would be a good idea. So I'll look into doing that. PS: could you link the mentioned discussion, it could help.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 20, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=9550



--- Comment #2 from Daniel Cousens <daniel350@bigpond.com> 2013-02-20 00:31:05 PST ---
(In reply to comment #1)
> Isn't what you are asking for a special case of sequence that discards any and all input?
> 
> //----
> int fun(T)(T/+Tuple!()+/, uint n)
> {
>     static int i;
>     return ++++i;
> }
> 
> void main()
> {
>     auto a = sequence!fun();
>     writeln(a.take(10));
> }
> //----
> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
> //----
> 
> In this case "T" is a tuple containing the empty state, and n is the iteration count.
> 
> Apart from the fancy sig, it's what you are asking for.
> 
> Given that the signature of "fun" isn't specified yet, we could special case
> sequence for sequences that have no initial state, to simply call fun(n) (as
> well as be more efficient).
> 
> I think it would be a good idea. So I'll look into doing that. PS: could you link the mentioned discussion, it could help.

Granted, that is what I'm asking for, but it seems as hackish (if not more confusing) then the iota solution.

The sequence solution does not sound very intuitive given the fact the output would change on each retrieval/take from the range.

The discussions have been over a many conversations, as I have run into this problem several times now, and finally resolved it isn't just something I have missed in phobos.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 20, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=9550



--- Comment #3 from monarchdodra@gmail.com 2013-02-20 01:15:30 PST ---
(In reply to comment #2)
> (In reply to comment #1)
> > Isn't what you are asking for a special case of sequence that discards any and all input?
> > 
> > //----
> > int fun(T)(T/+Tuple!()+/, uint n)
> > {
> >     static int i;
> >     return ++++i;
> > }
> > 
> > void main()
> > {
> >     auto a = sequence!fun();
> >     writeln(a.take(10));
> > }
> > //----
> > [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
> > //----
> > 
> > In this case "T" is a tuple containing the empty state, and n is the iteration count.
> > 
> > Apart from the fancy sig, it's what you are asking for.
> > 
> > Given that the signature of "fun" isn't specified yet, we could special case
> > sequence for sequences that have no initial state, to simply call fun(n) (as
> > well as be more efficient).
> > 
> > I think it would be a good idea. So I'll look into doing that. PS: could you link the mentioned discussion, it could help.
> 
> Granted, that is what I'm asking for, but it seems as hackish (if not more confusing) then the iota solution.
> 
> The sequence solution does not sound very intuitive given the fact the output would change on each retrieval/take from the range.
> 
> The discussions have been over a many conversations, as I have run into this problem several times now, and finally resolved it isn't just something I have missed in phobos.

FYI, sequence caches it's result, so if you just call front twice in a row, you *won't* get different values for each front. map *doesn't* cache its result, so you *will* get different results if you call front twice in a row.

As for intuitiveness, I personally prefer "sequence" over "map", but that may be because I actually use sequence and recurrence, so I'm more used to it.

A third alternative you could use is, instead of iota, you may want to consider using repeat:

//----
int fun(int)
{
    static int i;
    return ++++i;
}

void main()
{
    auto a = repeat(0).map!fun();
    writeln(a.take(10));
}
//----

The "advantage" this approach is that you define the range *mechanics*
(repeat+map) first, and then build the bounds on top of that (take).

Since take is infinite, there are chances it'll run faster too (operations such as length/empty will be easier to compute, since carried by the "top", as opposed to the "bottom").


//--------
But enough off-topic. You opened an enhancement request. Could you maybe
formalize your need a bit more, tell us in more detail what the semantics of
the range you are trying to build are? How you would use such a range? This
would help us better address the issue.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------