Poll: a nonstate keyword

Fawzi Mohamed fmohamed at mac.com
Sun Jun 1 10:08:26 PDT 2008


On 2008-06-01 15:31:12 +0200, "Janice Caron" <caron800 at googlemail.com> said:

> On 01/06/2008, Fawzi Mohamed <fmohamed at mac.com> wrote:
>> but needs at least a mixin in the destructor, or there is some magic that I
>> don't know yet?
> 
> There's some magic that you don't know about yet - specifically, that
> classes are allowed to have multiple destructors. When the object goes
> out of scope, all of its destructors are called. That means that the
> Cache! mixin I mentioned earlier only needs to define an additional
> destructor of its own.

nice!

>> I think for example that in the case of lazy linked list the external
>> hastable solution is probably too expensive, at leas twice as slow to
>> traverse, and with at least twice the overhead in memory.
> 
> Absolutely. However, if the standard library were to provide List!(T),
> then I think this need would go away.

The need of a mutable part in const comes form the lazyness of the 
construction of the list, not from the use of the list, any lazily 
constructed structure might need it.

let's look at a simple (and thus artificial) example (fully explicit, 
most of it can then be part of a mixin template) of what I want to be 
able to do: a lazy list of odd numbers from 1 to 1_000_000 (or even 
infinity)
This example as written is illegal and correctly so, but I want to be 
able to do something like this with a similar efficiency.

class ByTwo{
  int nAtt;
  private ByTwo *_next;
  this(int nAtt, ByTwo next){
    this.nAtt=nAtt;
    this._next=next;
  }
  ByTwo next() pure{
    if (_next==undefined){
     if (nAtt<1_000_000){
       _next=new ByTwo(nAtt+2,undefined);
     else
       _next=null;
    }
    return _next;
  }
}

Here undefined is just an invalid memory location 0x01, or if no such 
memory exist then just the address of an object that will stay around 
forever.

Now I might have a pure function like

int listLengthAcc(T)(T t,int length)pure{
  if (t is null) return length;
  return listLengthAcc(t.next,length+1);
}

and I want to call

listLengthAcc(cast(const) new ByTwo(1,undefined))

if everything would work this will use few memory, the stack will not 
grow and will return 499_999.

Note that the list is effectively constant from outside, and it is as 
if it would be there from the beginning, but it is potentially much 
more efficient from the memory point of view (and from the 
computational point of view in not all elements are needed).
This use is the (static) Lazy Caching (in the wiki).
To use it one could also use unsafe casts instead of some keyword, if 
it is guaranteed that no readonly memory (or something like it) are 
used.

>> Also for statistical information about calling pattern to a pure function
>> one probably doesn't want to spend much time/space.
> 
> It might not be possible to collect "statistical information about
> calling pattern to a pure function" anyway, since if the compiler does
> any decent optimization, then the number of times that a pure function
> is executed may have no bearing whatosever on the number of times that
> it's called. I think, the question, "How often would it have been
> executed if it wasn't pure?" can only be answered by not making it
> pure!

If I want to optimize the function I want the answer to the calling 
pattern of a pure function with all optimization.
Not a common use case, and it can be hacked around ad hoc, but still 
not unresonable.





More information about the Digitalmars-d mailing list