mutable keyword

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat May 21 02:07:06 PDT 2016


On Saturday, May 21, 2016 07:00:43 ciechowoj via Digitalmars-d-learn wrote:
> On Saturday, 21 May 2016 at 00:39:21 UTC, Jonathan M Davis wrote:
> > Well, if you actually tried marking functions with pure, you'd
> > see pretty fast that this won't work with pure. A function
> > that's marked with pure cannot access any global, mutable
> > state. It can only access what's passed to it (though in the
> > case of a member function, that includes the this
> > pointer/reference). So, your refCountPool will not be
> > accessible from any pure functions.
>
> Well, I do not have much experience with @pure in D. But I
> believe that as far as I'm not using refCounter-modifying methods
> of sharedPtr (constructors, assignement, destructor) it should
> work. Maybe I'll try it in some future.

The problem is the global variable you were using. If the ref-counting is
completely internal, then it can be pure, but it can't access global
variables. I'd suggest that you read this article:

http://klickverbot.at/blog/2012/05/purity-in-d/

> > You can think of pure as @noglobal, because it can't access
> > global variables (unless they're constants). That's it's only
> > restriction, but it's enough to make it so that the only way
> > that you'd have a backdoor out of const in a pure, const member
> > function is if you passed a mutable reference to the object as
> > one of the function arguments.
> >
> > At this point, if you want ref-counting, you give up on const.
> > They simply do not go together. The same goes for stuff like
> > caching or lazy initialization.
> >
> > Sure, you can get around const to some extent by giving up on
> > pure, but that only works because you're putting the state of
> > the object outside of the object itself, which is usally a bad
> > idea. It also makes it so that const seems like a lie, since
> > the state of the object isn't really const, since it's not
> > actually in the object.
>
> I didn't tried the proposed solution, but if this is only
> ideological problem and not a technical one, I would be good with
> such a solution. On one side the memory reachable from object
> isn't modified on the other side the object feels like a const
> for the end-used. I mean I miss a logical const from C++ : ).

Well, any function that isn't marked with pure is completely unusable in
pure code, and it's generally best practice in D to use pure as much as
possible. It makes it clear that the functions in question can't access
anything that you don't give them, it allows for compiler optimizations in
some cases, and it also makes it easier to do stuff like construct immutable
objects, since if the compiler can guarantee that the return value of a pure
function is unique, it can be implicitly converted to immutable (it might
also be implicitly convertible to shared - I don't recall for sure). And of
course, if you're interacting with D code that requires pure, then your code
is going to need to work with pure.

And since const is already borderline useless for heavily templated code
(which anything range-based tends to be), contorting your code to favor
const over pure is ill-advised.

>From what I've seen, pretty much everyone who wants to do stuff like
ref-counting or lazy initialization abandons trying to use const. So, if you
need "mutable," I'd strongly encourage you to do the same rather than trying
to put state in global variables just to have "logical" const, but it's up
to you.

> > The standard library already has std.typecons.RefCounted, if
> > you want to ref-count anything other than classes, but it
> > really doesn't work with const and fundamentally can't. In
> > order to have const ref-counting, we're going to need language
> > support. D does not and likely will never have any form of
> > "logical" const. If it's const, it's const. Either that fits
> > with what you're doing, and you can use const, or it doesn't,
> > and you can't.
>
> I'm currently doing that, but std.typecons.RefCounted is
> uncomfortable to use. Probably for reasons mentioned above.

Well, fundamentally, ref-counting and const don't mix. C++ allows it by
basically making it so that C++'s const guarantees nothing. All it really
does is prevent accidental mutation and function as documentation that a
member function isn't supposed to modify its object's state. But nothing is
really guaranteed. D's const provides actual guarantees, but the result is
that it's usuable in far fewer cases, because a lot of code simply doesn't
work if it's forced to actually be const.

So, RefCounted will work on some level, but it really isn't going to work
with const, and no library solution even _can_ play nicely with const - not
without throwing pure out the window anyway, and the really isn't worth it,
especially since we keep getting more stuff added to the language that's
able to take advantage of pure.

But Walter is working on a language solution for ref-counting, and with
that, it should become possible for ref-counting to play nicely with const.

Still, I get the impression that most D programmers use const pretty
limitedly, because trying to use it like you would in C++ simply does not
play nicely with D - especially idiomatic D, which is generally range-based.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list