On 11/21/2010 02:43 AM, Michel Fortin wrote:
On 2010-11-20 09:21:04 -0500, Peter Alexander
<peter.alexander...@gmail.com> said:

D does not support logical const due to the weak guarantees that it
provides.

So, without logical const, how are D users supposed to provide lazy
evaluation and memoization in their interfaces, given that the
interface should *seem* const, e.g.

class Matrix
{
double getDeterminant() const { /* expensive calculation */ }
}

If it turns out that getDeterminant is called often with the raw
matrix data remaining unchanged, how can we add caching to this class
without rewriting the const-ness of all code that touches it?

Using a static associative array as a cache will work:

class Matrix
{
double getDeterminant() const
{
static double[const(Matrix)] cache;
if (auto resultptr = (this in cache))
return *resultptr;

auto result = /* expensive calculation */;
cache[this] = result;
return result;
}
}

and it'll continue to work even if you pass an immutable Matrix to
different threads (each thread has its own cache). If you don't pass
immutable Matrixes across threads, then you don't gain anything by
making the function const.

The main reason D has const is to facilitate the usage of immutable. If
you don't use immutable for a given type you generally shouldn't bother
with const either.

But in any case, you always can cast away const if you really need to,
just be sure of what you're doing. For instance, doing this breaks
thread-safety for immutable Matrixes:

auto mutableThis = cast(Matrix)this;
mutableThis.cachedDeterminant = /* expensive calculation */;



I am also interested in what is the D way of doing this. The associative array approach is not suitable for the case of 4x4 matrices in a 3D application where you can have thousonds of them.

At some point, the associative array lookup will be more expensive than the actual calculation.

j.

Reply via email to