| Thread overview | |||||||||
|---|---|---|---|---|---|---|---|---|---|
|
July 09, 2014 Passing Templated Function Arguments Solely by Reference | ||||
|---|---|---|---|---|
| ||||
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 Re: Passing Templated Function Arguments Solely by Reference | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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 Re: Passing Templated Function Arguments Solely by Reference | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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 Re: Passing Templated Function Arguments Solely by Reference | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: Passing Templated Function Arguments Solely by Reference | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: Passing Templated Function Arguments Solely by Reference | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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 Re: Passing Templated Function Arguments Solely by Reference | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Friday, 11 July 2014 at 17:43:53 UTC, Ali Çehreli wrote:
> Ali
Thx
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply