www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Passing Templated Function Arguments Solely by Reference

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
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?
Jul 08 2014
next sibling parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
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.
Jul 08 2014
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Jul 09 2014
next sibling parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
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
Jul 11 2014
prev sibling parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
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) ?
Jul 11 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Jul 11 2014
parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Friday, 11 July 2014 at 17:43:53 UTC, Ali Çehreli wrote:
 Ali
Thx
Jul 13 2014