www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Question about Walter's Memory DisAllocation pattern

reply Parke via Digitalmars-d <digitalmars-d puremagic.com> writes:
Hi,

I have a question about Walter's DConf keynote and the Memory
DisAllocation pattern.

http://dconf.org/2015/talks/bright.html

The following example is from the slides of Walter's talk.

----

auto toString(uint u) {
  static struct Result {
    this(uint u) {
      idx = buf.length;
      do {
        buf[--idx] = (u % 10) + '0';
        u /= 10;
      } while (u);
    }
     property bool empty() { return idx == buf.length; }
     property char front() { return buf[idx]; }
    void popFront() { ++idx; }
    char[uint.sizeof * 3] buf;
    size_t idx;
  }
  return Result(u);
}

import std.stdio;

void main() { writeln(toString(28)); }

----

My question is:

Does use of this pattern in D require that the size of the Result
struct be known by the compiler at compile time?

Or, perhaps more precisely:  Does the caller of toString need to know
the size of the struct that toString will return?

In the above example, buf's length is uint.sizeof * 3.  But what if
buf's length was a function of u (and therefore only known at
run-time), rather than a function of uint.sizeof?

Thanks!

-Parke
Jun 26 2015
next sibling parent reply Etienne Cimon <etcimon gmail.com> writes:
On 2015-06-26 22:45, Parke via Digitalmars-d wrote:
 Hi,

 I have a question about Walter's DConf keynote and the Memory
 DisAllocation pattern.

 http://dconf.org/2015/talks/bright.html

 The following example is from the slides of Walter's talk.

 ----

 auto toString(uint u) {
    static struct Result {
      this(uint u) {
        idx = buf.length;
        do {
          buf[--idx] = (u % 10) + '0';
          u /= 10;
        } while (u);
      }
       property bool empty() { return idx == buf.length; }
       property char front() { return buf[idx]; }
      void popFront() { ++idx; }
      char[uint.sizeof * 3] buf;
      size_t idx;
    }
    return Result(u);
 }

 import std.stdio;

 void main() { writeln(toString(28)); }

 ----

 My question is:

 Does use of this pattern in D require that the size of the Result
 struct be known by the compiler at compile time?

 Or, perhaps more precisely:  Does the caller of toString need to know
 the size of the struct that toString will return?

 In the above example, buf's length is uint.sizeof * 3.  But what if
 buf's length was a function of u (and therefore only known at
 run-time), rather than a function of uint.sizeof?

 Thanks!

 -Parke
What you're asking for is probably type inference. Notice the auto return type? This keyword is actually very advanced and bleeding edge in natively compiled languages. Internally, when the function is processed by the compiler, all types are evaluated before the instructions are even looked at, and the final size of all types are compiled and automatically put in place. Afterwards, the instructions must obey consistency, ie. the caller can't use anything but auto or ReturnType!toString to accept an auto type because there's no way you can guess the mangling/size/etc otherwise. This also means you can choose a ridiculous name or you can change the size of a stack allocated object any time without breaking an interface. e.g. you could change this without breaking the API to something like: auto toString(T)(T u) if (isNumeric!T) { static struct GenericResult { this(T u) { ... char[T.sizeof * 3] buf; ... }
Jun 26 2015
parent reply "thedeemon" <dlang thedeemon.com> writes:
On Saturday, 27 June 2015 at 03:10:51 UTC, Etienne Cimon wrote:

 What you're asking for is probably type inference. Notice the 
 auto return type? This keyword is actually very advanced and 
 bleeding edge in natively compiled languages.
Inference of return type was in ML since 1973. Such bleeding, so edge. ;)
Jun 26 2015
parent reply Etienne Cimon <etcimon gmail.com> writes:
On 2015-06-27 01:06, thedeemon wrote:
 On Saturday, 27 June 2015 at 03:10:51 UTC, Etienne Cimon wrote:

 What you're asking for is probably type inference. Notice the auto
 return type? This keyword is actually very advanced and bleeding edge
 in natively compiled languages.
Inference of return type was in ML since 1973. Such bleeding, so edge. ;)
Is there some other natively compiled language that implemented the auto keyword before? Or are you only talking about the theory?
Jun 27 2015
parent "thedeemon" <dlang thedeemon.com> writes:
On Saturday, 27 June 2015 at 11:11:31 UTC, Etienne Cimon wrote:
 On 2015-06-27 01:06, thedeemon wrote:
 Inference of return type was in ML since 1973. Such bleeding, 
 so edge. ;)
Is there some other natively compiled language that implemented the auto keyword before? Or are you only talking about the theory?
ML, SML, OCaml, Haskell, Idris - all of them natively compiled, all can infer return types as well as virtually all the other types. They don't use "auto" keyword, of course, the syntax is different. You just write let f x y = x + String.length y and OCaml (in this case) compiler knows that x is int, y is string and return type is int.
Jun 27 2015
prev sibling next sibling parent "thedeemon" <dlang thedeemon.com> writes:
On Saturday, 27 June 2015 at 02:51:18 UTC, Parke wrote:

 In the above example, buf's length is uint.sizeof * 3.  But 
 what if buf's length was a function of u (and therefore only 
 known at run-time), rather than a function of uint.sizeof?
In this case you have two options: 1) do not store result in a buffer but calculate data in the range methods (front() and popFront()) 2) allocate and give up this disallocation pattern
Jun 26 2015
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/26/2015 7:45 PM, Parke via Digitalmars-d wrote:
 Or, perhaps more precisely:  Does the caller of toString need to know
 the size of the struct that toString will return?
Yes.
 In the above example, buf's length is uint.sizeof * 3.  But what if
 buf's length was a function of u (and therefore only known at
 run-time), rather than a function of uint.sizeof?
In cases where the size cannot be known in advance, the returned struct can malloc/free the extra space.
Jun 27 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/27/15 3:24 PM, Walter Bright wrote:
 On 6/26/2015 7:45 PM, Parke via Digitalmars-d wrote:
 Or, perhaps more precisely:  Does the caller of toString need to know
 the size of the struct that toString will return?
Yes.
 In the above example, buf's length is uint.sizeof * 3.  But what if
 buf's length was a function of u (and therefore only known at
 run-time), rather than a function of uint.sizeof?
In cases where the size cannot be known in advance, the returned struct can malloc/free the extra space.
Be careful with this. You need a reference counted type to do this properly (or make the result not copyable). Also, malloced data is not scanned for pointers by the GC. -Steve
Jun 30 2015
parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/30/2015 6:05 AM, Steven Schveighoffer wrote:
 Be careful with this. You need a reference counted type to do this properly (or
 make the result not copyable).
I presume the person doing such knows what he's doing. It's why malloc/free are system code.
Jun 30 2015