rvalue types

Shachar Shemesh shachar at weka.io
Mon Mar 12 14:19:17 UTC 2018


I'll just point out that the C++ name for this is "Proxy classes". 
Maybe, for the sake of reducing confusion, it might be a good idea to 
adopt that.

Shachar

On 12/03/18 15:59, Simen Kjærås wrote:
> There's been a discussion[0] over in D.learn about a library-only 
> implementation of properties. One of the ideas mentioned there is rvalue 
> types - types that automatically decay into a different type when passed 
> to a function or assigned to a variable. They are useful for property 
> wrappers like this, and when you want to perform a series of operations 
> on something before performing some final step.
> 
> An example of the latter is `a ^^ b % c` for BigInts, where the naïve 
> way would be horribly inefficient, and there's a much better way of 
> doing it, which requires more knowledge of the operations involved. If 
> `a ^^ b` returned an rvalue type that either decays to a regular BigInt 
> or acts as the LHS in `tmp % c`, it would have the necessary information 
> and be able to do the right thing.
> 
> Another use case is a chain of operations, e.g. fluent initialization:
> 
> Widget.create()
>      .width(35)
>      .height(960)
>      .data(readData())
>      .Done();
> 
> Where in current D the Done() step needs to be explicit, an rvalue type 
> would automatically call Done when the result is assigned to a variable 
> or passed to a function.
> 
> The problem with such a set of types, of course, is that 
> `typeof(functionThatReturnsRvalueType())` will be different from 
> `typeof((){ auto t = functionThatReturnsRvalueType(); return t;}())`, 
> and that bleeds into documentation. It may also be confusing that 
> `return a ^^ b % c;` is much faster than `auto tmp = a ^^ b; return tmp 
> % c;`.
> 
> An example of how they would work:
> 
> struct ModularExponentiationTemporary {
>      BigInt lhs, rhs;
> 
>      @rvalue // Or however one would mark it as such.
>      alias get this;
> 
>      BigInt get() {
>          return pow(lhs, rhs);
>      }
> 
>      BigInt opBinaryRight(string op : "%")(BigInt mod) {
>          return modularPow(lhs, rhs, mod);
>      }
> }
> 
> unittest {
>      BigInt b = 4;
>      BigInt e = 13
>      BigInt m = 497;
> 
>      // b ^^ e returns a ModularExponentiationTemporary,
>      // and its opBinaryRight() is immediately invoked.
>      auto fast = b ^^ e % m;
> 
>      assert(is(typeof(fast) == BigInt));
>      assert(fast== 445);
> 
>      // b ^^ e returns a ModularExponentiationTemporary,
>      // and its get() method is immediately invoked.
>      auto slowTmp = b ^^ e;
>      auto slow = slowTmp % m;
> 
>      assert(is(typeof(slowTmp == t) == BigInt));
>      assert(is(typeof(slow) == BigInt));
>      assert(slow == 445);
> }
> 
> Is this an interesting concept? Are there other use cases I haven't 
> covered? Can this be done with existing language features? Are there 
> problems I haven't foreseen?
> 
> -- 
>    Simen
> 
> [0]: https://forum.dlang.org/post/mqveusvzkmkshrzwsgjy@forum.dlang.org



More information about the Digitalmars-d mailing list