Thread overview
Lazily evaluated property pointing to read only object
Sep 24, 2016
mikey
Sep 24, 2016
Basile B.
Sep 24, 2016
mikey
Sep 24, 2016
Basile B.
Sep 27, 2016
vit
September 24, 2016
I'm trying to figure out how to best write a class with a property that is only evaluated when it's called for the first time. And that returns an object which shouldn't be modifiable a part of the owning class.

I've had a go at doing something like this but am not very sure if this is how to go about it.


    class Obj {
        string _s;

        this() {
            this("");
        }

        this(string s) {
            _s = s;
        }

        @property string desc() const { return _s; }
        @property void desc(string s) { _s = s; }

        override string toString() const {
            return _s;
        }
    }

    class ConstProp {
        Obj _o;
        string _s;

        this(string s) {
            _s = s;
        }

        const(Obj) lazily() {
            if (_o is null) {
                _o = new Obj("working " ~ _s);
            }
            return cast(const(Obj)) _o;
        }
    }

    void main() {
        auto c = new ConstProp("test");
        writeln(c.lazily);
        writeln(c.lazily.desc);
    }
September 24, 2016
On Saturday, 24 September 2016 at 09:08:52 UTC, mikey wrote:
> I'm trying to figure out how to best write a class with a property that is only evaluated when it's called for the first time. And that returns an object which shouldn't be modifiable a part of the owning class.
>
> I've had a go at doing something like this but am not very sure if this is how to go about it.
> [...]
>
>
>         const(Obj) lazily() {
>             if (_o is null) {
>                 _o = new Obj("working " ~ _s);
>             }
>             return cast(const(Obj)) _o;
>         }
>     }

You don't need to cast, from "mutable" to "const" is implicit:
https://dlang.org/spec/const3.html#implicit_conversions
September 24, 2016
On Saturday, 24 September 2016 at 10:16:34 UTC, Basile B. wrote:
> You don't need to cast, from "mutable" to "const" is implicit:
> https://dlang.org/spec/const3.html#implicit_conversions

Ok, but using const would be an accepted way of doing this? The options I could see were to have "_o" as a const or immutable type and just create a const on the first call to the lazily evaluated property, or to do what I did and have "_o" as a non-const and then convert it to cost on the way out. However

To store it as const I guess I'd have to make it a non-const pointer to a const object, and is that not kind of what immutable is?


September 24, 2016
On Saturday, 24 September 2016 at 10:59:50 UTC, mikey wrote:
> On Saturday, 24 September 2016 at 10:16:34 UTC, Basile B. wrote:
>> You don't need to cast, from "mutable" to "const" is implicit:
>> https://dlang.org/spec/const3.html#implicit_conversions
>
> Ok, but using const would be an accepted way of doing this? The options I could see were to have "_o" as a const or immutable type and just create a const on the first call to the lazily evaluated property, or to do what I did and have "_o" as a non-const and then convert it to cost on the way out. However
>
> To store it as const I guess I'd have to make it a non-const pointer to a const object, and is that not kind of what immutable is?

Yes, the problem is that if you want to create a true const(Object) (with const part of the type) you have to initialize it in a constructor (so no lazyness). It indeed looks like the immutable mechanism. I don't know **exactly** why but I guess that's a special case for classes since there's no other way to initialize them.

Finally, with the property your object is seen as const(Object) outside. The only difference is inside ConstProp.
September 27, 2016
On Saturday, 24 September 2016 at 11:51:56 UTC, Basile B. wrote:
> On Saturday, 24 September 2016 at 10:59:50 UTC, mikey wrote:
>> On Saturday, 24 September 2016 at 10:16:34 UTC, Basile B. wrote:
>>> You don't need to cast, from "mutable" to "const" is implicit:
>>> https://dlang.org/spec/const3.html#implicit_conversions
>>
>> Ok, but using const would be an accepted way of doing this? The options I could see were to have "_o" as a const or immutable type and just create a const on the first call to the lazily evaluated property, or to do what I did and have "_o" as a non-const and then convert it to cost on the way out. However
>>
>> To store it as const I guess I'd have to make it a non-const pointer to a const object, and is that not kind of what immutable is?
>
> Yes, the problem is that if you want to create a true const(Object) (with const part of the type) you have to initialize it in a constructor (so no lazyness). It indeed looks like the immutable mechanism. I don't know **exactly** why but I guess that's a special case for classes since there's no other way to initialize them.
>
> Finally, with the property your object is seen as const(Object) outside. The only difference is inside ConstProp.

use Rebindable:


class Obj {
        string _s;

        this()pure{
            this("");
        }
        this(string s)pure{
            _s = s;
        }

        @property string desc() const { return _s; }
        @property void desc(string s) { _s = s; }

        override string toString() const {
            return _s;
        }
    }

class ConstProp {
    import std.typecons : Rebindable;
    Rebindable!(immutable Obj) _o;
    string _s;

    this(string s) {
        _s = s;
    }

    immutable(Obj) lazily(){
        if (_o is null) {
            _o = new Obj("working " ~ _s);
        }
        return _o;
    }
}