Thread overview
Passing Templated Function Arguments Solely by Reference
Jul 09, 2014
Nordlöw
Jul 09, 2014
Nordlöw
Jul 09, 2014
Ali Çehreli
Jul 11, 2014
Nordlöw
Jul 11, 2014
Nordlöw
Jul 11, 2014
Ali Çehreli
Jul 13, 2014
Nordlöw
July 09, 2014
If I want randInPlace to take value arguments (such as structs) by reference and reference types (classes) as normal is this

/** Generate Random Contents in $(D x).
 */
auto ref randInPlace(T)(auto ref T x) @safe /* nothrow */ if (isIterable!T)
{
    foreach (ref elt; x)
    {
        import std.range: ElementType;
        static if (isInputRange!(ElementType!T))
            elt[].randInPlace;
        else
            elt.randInPlace;
    }
    return x;
}

the way to do it or does

    auto ref T x

evaluate to unnecessary

    ref Class x

?

And isIterable the recommended way to do it?

And how does this compare to using x[].randInPlace() when x is a static array? Does x[] create unnecessary GC-heap activity in this case?

I'm wondering because (auto ref T x) is just used in two places in std.algorithm and std.range in Phobos. Is this a relatively new enhancement?
July 09, 2014
On Wednesday, 9 July 2014 at 00:13:41 UTC, Nordlöw wrote:

Searching for

"Function Templates with Auto Ref Parameters"

on http://dlang.org/template.html answered my first question.

I'm however still uncertain how to implement randInPlace in the most D idiomatic way.
July 09, 2014
On 07/08/2014 05:13 PM, "Nordlöw" wrote:

> If I want randInPlace to take value arguments (such as structs) by
> reference and reference types (classes) as normal is this

I don't understand what it means to fill a struct or a class object with random content.

> /** Generate Random Contents in $(D x).
>   */
> auto ref randInPlace(T)(auto ref T x) @safe /* nothrow */ if (isIterable!T)

hasAssignableElements is more correct.

> {
>      foreach (ref elt; x)
>      {
>          import std.range: ElementType;
>          static if (isInputRange!(ElementType!T))

The documentation of hasAssignableElements mentions that it implies isForwardRange and it makes sense: You don't want the range to be consumed as an InputRange would do.

>              elt[].randInPlace;
>          else
>              elt.randInPlace;
>      }
>      return x;
> }

> And how does this compare to using x[].randInPlace() when x is a static
> array?

Range algorithms don't work with static arrays because they can't popFront(). The solution is to use a slice to the entire array as you've already done as x[]. ;)

> Does x[] create unnecessary GC-heap activity in this case?

No. Static array will remain in memory and x[] will be a local slice. A slice consists of two members, the equivalent of the following:

struct __SliceImpl
{
    size_t length;
    void * pointer_to_first_element;
}

> I'm wondering because (auto ref T x) is just used in two places in
> std.algorithm and std.range in Phobos. Is this a relatively new
> enhancement?

Phobos algorithms use ranges. The following is what I've come up with very quickly:

import std.stdio;
import std.range;
import std.traits;
import std.random;

void randInPlace(R)(R range)
    if (hasAssignableElements!R)
{
    foreach (ref e; range) {
        e.randInPlace();
    }
}

void randInPlace(E)(ref E element)
    if (isNumeric!E)
{
    // BUG: Never assigns the value E.max
    element = uniform(E.min, E.max);
}

void randInPlace(E)(ref E element)
    if (isBoolean!E)
{
    element = cast(bool)uniform(0, 2);
}

void main()
{
    auto arr = [ [ 0, 1, 2 ], [ 3, 4, 5 ] ];
    arr.randInPlace();
    writefln("%s", arr);

    auto barr = [ [ false, true ], [ false, true ] ];
    barr.randInPlace();
    writefln("%s", barr);
}

Ali

July 11, 2014
On Wednesday, 9 July 2014 at 07:43:57 UTC, Ali Çehreli wrote:
> Phobos algorithms use ranges. The following is what I've come up with very quickly:

Thx
July 11, 2014
On Wednesday, 9 July 2014 at 07:43:57 UTC, Ali Çehreli wrote:
> Ali

This

https://github.com/nordlow/justd/blob/master/random_ex.d

is what I have so far. Does this look ok to you?

Question: Can I somehow avoid the duplication of logic in

- auto ref randInPlace(R)(R x) @safe if (hasAssignableElements!R)
- auto ref randInPlace(T)(ref T x) @safe if (isStaticArray!T)

?
July 11, 2014
On 07/11/2014 03:38 AM, "Nordlöw" wrote:

> https://github.com/nordlow/justd/blob/master/random_ex.d
>
> is what I have so far. Does this look ok to you?

The following seems redundant because the other isFloatingPoint!E version uses the default arguments 0 and 1 anyway.

auto ref randInPlace(E)(ref E x) @trusted if (isFloatingPoint!E)
{
    return x = uniform(cast(E)0,
                       cast(E)1);
}

> Question: Can I somehow avoid the duplication of logic in
>
> - auto ref randInPlace(R)(R x) @safe if (hasAssignableElements!R)
> - auto ref randInPlace(T)(ref T x) @safe if (isStaticArray!T)

The following works if you pardon the name foo. :p

auto foo(TT)(ref TT x)
{
    foreach (ref e; x)
    {
        e.randInPlace;
    }
    return x;
}

/** Generate Random Contents in $(D x).
 */
auto ref randInPlace(R)(auto ref R x) @safe if (hasAssignableElements!R)
{
    return foo(x);
}

/** Generate Random Contents in $(D x).
 */
auto ref randInPlace(T)(ref T x) @safe if (isStaticArray!T)
{
    return foo(x);
}

Alternatively, a string mixin could be used but they should be reserved for when there is no better solution.

Ali

July 13, 2014
On Friday, 11 July 2014 at 17:43:53 UTC, Ali Çehreli wrote:
> Ali

Thx