rvalue types

Dmitry Olshansky dmitry.olsh at gmail.com
Tue Mar 13 06:51:01 UTC 2018


On Monday, 12 March 2018 at 19:03:10 UTC, H. S. Teoh wrote:
> On Mon, Mar 12, 2018 at 06:46:56PM +0000, Simen Kjærås via 
> Digitalmars-d wrote:
>> On Monday, 12 March 2018 at 16:51:06 UTC, H. S. Teoh wrote:
>> > I suspect the current language already supports this, or is 
>> > 90% of the way there and just needs some small concessions 
>> > on syntax.  For example, today you can already make 
>> > opBinary() return something other than the parent type, and 
>> > use alias this to make it decay to the parent type. Of 
>> > course, this requires the caller to write `BigInt x = a^^b % 
>> > c` rather than `auto x = a^^b % c`, but I think that's a 
>> > minor inconvenience.
>> 
>> I mostly agree, but it can play havoc on generic code. On the 
>> other hand, if we don't think carefully through how they 
>> should work, so would rvalue types.
> [...]
>
> Actually, I'm even wondering if allowing the assignment of an 
> intermediate type might not necessarily be a bad thing.  
> Suppose BigInt.opBinary returns some intermediate type, like 
> BigIntIntermediate, that implicitly converts to BigInt via 
> alias this.  If you write:
>
> 	BigInt a, b, c;
> 	auto x = a*b + c;
>
> then x will be a BigIntIntermediate instead of a BigInt. But is 
> that really so bad?

When combined with a few range primitives exponental template 
bloat is inevitable.

While writing Pry I soon come to realize that using types to 
store information is a dead end. They are incredibly brittle esp. 
once you start optimizing on them using operations such as T1 
eqivalent to T2, where T1 != T2.
And slow. Did I meantioned they are slow? And ofc 64kbyte symbols 
that make no sense anyway.

A better approach for cases beyond a handful operators is so 
called “staging” - 2 stage computation, where you first build a 
blueprint of operation using CTFE. Secondly you “instantiate it” 
and apply arbitrarry number of times. Optimization opportunities 
inbetween those stages are remarkable and much easier to grasp 
compared to “type dance”.

For instance:

enum Expr!double bluePrint = factor!”a” ^^ factor!”b” % 
factor!”c”;

Where that Expr is eg a class instance that holds AST of operaton 
as plain values.

Now usage:

alias powMod = bluePrint.instantiate; // here we do optimizations 
and CTFE-based codegen

powMod(a,b,c); // use as many times as needed

Notation could be improved by using the same expression template 
idea but with polymorphic types at CTFE.

Another thing is partial specialization:

alias squareMod = bluePrint.assume({ “b” : 2 }).instantiate;

Now :

squareMod(a,c); // should be faster the elaborate algorithm



More information about the Digitalmars-d mailing list