protocol for using InputRanges

Rainer Schuetze r.sagitario at gmx.de
Wed Mar 26 23:53:28 PDT 2014



On 27.03.2014 03:48, Walter Bright wrote:
> On 3/26/2014 7:19 PM, Steven Schveighoffer wrote:
>> if(!r.empty)
>> {
>>     auto r2 = map!(x => x * 2)(r);
>>     do
>>     {
>>        auto x = r2.front;
>>        ...
>>     } while(!r2.empty);
>> }
>>
>> Should we be required to re-verify that r2 is not empty before using
>> it? It
>> clearly is not, and would be an artificial requirement (one that map
>> likely
>> would not enforce!).
>>
>> This sounds so much like a convention that simply won't be followed,
>> and the
>> result will be perfectly valid code.
>
> The idea is that there are three functions: empty, front, and popFront.
> The functionality of the range will be distributed between these 3
> functions. Different things being ranged over will naturally split their
> operations into the 3 functions in different ways.
>
> If the 3 functions can be called in any order, then extra logic has to
> be added to them to signal to each other. This slows things down.
>
> To write generic code calling ranges, it's necessary to stop assuming
> what is happening under the hood of empty, front, and popFront, and
> stick to the protocol.
>

IIUC what you are proposing would be covered better by removing front 
and return the value by popFront.

Instead of forcing strong, breaking and sometimes unintuitive semantics 
we could also improve dmd's optimizer. This caching range example:

///////////////////////////////////
T getc(T)();

struct irange(T)
{
   bool _cached;
   T _cache;

   this(T[] arr) { _cached = false; }
   bool empty() {
     if(_cached) return false;
     _cache = getc!T();
     return (_cache < 0);
   }
   T front() { empty(); return _cache; }
   void popFront() { _cached = false; }
}

int foo(irange!int rg)
{
   int sum = 0;
   while(!rg.empty)
   {
     sum += rg.front;
   	rg.popFront;
   }
   return sum;
}
///////////////////////////////////

generates this code with "dmd2.065 -O -inline -release -noboundscheck -m64":

_D7irange23fooFS7irange213__T6irangeTiZ6irangeZi:
   0000: push        rbp
   0001: mov         rbp,rsp
   0004: push        rax
   0005: push        rsi
   0006: mov         qword ptr [rbp+10h],rcx
   000A: xor         esi,esi
   000C: lea         rcx,[rbp+10h]
   0010: sub         rsp,20h
   0014: call        _D7irange213__T6irangeTiZ6irange5emptyMFZb
   0019: add         rsp,20h
   001D: xor         al,1
   001F: je          0050
   0021: lea         rcx,[rbp+10h]
   0025: sub         rsp,20h
   0029: call        _D7irange213__T6irangeTiZ6irange5emptyMFZb
   002E: add         rsp,20h
   0032: mov         eax,dword ptr [rbp+14h]
   0035: add         esi,eax
   0037: mov         byte ptr [rbp+10h],0
   003B: lea         rcx,[rbp+10h]
   003F: sub         rsp,20h
   0043: call        _D7irange213__T6irangeTiZ6irange5emptyMFZb
   0048: add         rsp,20h
   004C: xor         al,1
   004E: jne         0021
   0050: mov         eax,esi
   0052: pop         rsi
   0053: lea         rsp,[rbp]
   0057: pop         rbp
   0058: ret

_D7irange213__T6irangeTiZ6irange5emptyMFZb:
   0000: push        rbp
   0001: mov         rbp,rsp
   0004: mov         qword ptr [rbp+10h],rcx
   0008: cmp         byte ptr [rcx],0
   000B: je          0011
   000D: xor         eax,eax
   000F: pop         rbp
   0010: ret
   0011: sub         rsp,20h
   0015: call        _D7irange211__T4getcTiZ4getcFZi
   001A: add         rsp,20h
   001E: mov         rcx,qword ptr [rbp+10h]
   0022: mov         dword ptr [rcx+4],eax
   0025: shr         eax,1Fh
   0028: mov         byte ptr [rcx],al
   002A: xor         al,1
   002C: pop         rbp
   002D: ret

and this with gdc (-O2 on godbolt.org):

int example.foo(example.irange!(int).irange):
	mov	rax, rdi
	push	rbx
	xor	ebx, ebx
	shr	rax, 32
	test	dil, dil
	je	.L5
.L2:
	add	ebx, eax
.L5:
	call	int example.getc!(int).getc()
	test	eax, eax
	js	.L2
	mov	eax, ebx
	pop	rbx
	ret

All traces of the caching but the initial state check have been removed, 
no extra calls.


More information about the Digitalmars-d mailing list