Thread overview
Cached property (translate Python -> D)
Jan 29, 2019
Victor Porton
Jan 29, 2019
Daniel Kozak
Jan 29, 2019
Victor Porton
Jan 29, 2019
Nicholas Wilson
Jan 29, 2019
Victor Porton
Jan 29, 2019
H. S. Teoh
Jan 29, 2019
Victor Porton
January 29, 2019
I want to translate if possible the following from Python to D. Please help.

---
class cached_property(object):
    """A version of @property which caches the value.  On access, it calls the
    underlying function and sets the value in `__dict__` so future accesses
    will not re-call the property.
    """
    def __init__(self, f):
        self._fname = f.__name__
        self._f = f

    def __get__(self, obj, owner):
        assert obj is not None, 'call {} on an instance'.format(self._fname)
        ret = obj.__dict__[self._fname] = self._f(obj)
        return ret
---
January 29, 2019
Maybe https://dlang.org/phobos/std_functional.html#memoize should helped you

On Tue, Jan 29, 2019 at 4:15 PM Victor Porton via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> I want to translate if possible the following from Python to D. Please help.
>
> ---
> class cached_property(object):
>      """A version of @property which caches the value.  On access,
> it calls the
>      underlying function and sets the value in `__dict__` so
> future accesses
>      will not re-call the property.
>      """
>      def __init__(self, f):
>          self._fname = f.__name__
>          self._f = f
>
>      def __get__(self, obj, owner):
>          assert obj is not None, 'call {} on an
> instance'.format(self._fname)
>          ret = obj.__dict__[self._fname] = self._f(obj)
>          return ret
> ---
>


January 29, 2019
On Tuesday, 29 January 2019 at 15:12:37 UTC, Victor Porton wrote:
> I want to translate if possible the following from Python to D. Please help.
>
> ---
> class cached_property(object):
>     """A version of @property which caches the value.  On access, it calls the
>     underlying function and sets the value in `__dict__` so future accesses
>     will not re-call the property.
>     """
>     def __init__(self, f):
>         self._fname = f.__name__
>         self._f = f
>
>     def __get__(self, obj, owner):
>         assert obj is not None, 'call {} on an instance'.format(self._fname)
>         ret = obj.__dict__[self._fname] = self._f(obj)
>         return ret
> ---

Please use the learn forum for such questions. Thanks!
January 29, 2019
On Tuesday, 29 January 2019 at 15:26:13 UTC, Daniel Kozak wrote:
> Maybe https://dlang.org/phobos/std_functional.html#memoize should helped you

No, this does not compile:

struct C {
    int _f() { writeln("Got!"); return 2; }
    alias f = memoize!_f;
}
January 29, 2019
I've successfully implemented it myself:

---
import std.stdio;

mixin template Cached(string name, string baseName = '_' ~ name) {
    mixin("private typeof(" ~ baseName ~ ") " ~ name ~ "Cache;");
    mixin("private bool " ~ name ~ "IsCached = false;");
    mixin("@property typeof(" ~ baseName ~ ") " ~ name ~ "() {\n" ~
          "if (" ~ name ~ "IsCached" ~ ") return " ~ name ~ "Cache;\n" ~
          name ~ "IsCached = true;\n" ~
          "return " ~ name ~ "Cache = " ~ baseName ~ ";\n" ~
          '}');
}

struct C {
    @property int _f() { writeln("Got!"); return 2; }
    mixin Cached!"f";
}

void main(string[] args)
{
    C x;
    writeln(x.f);
    writeln(x.f);
}
---

I think, we should add this to the standard library. What do you think?
January 29, 2019
On Tue, Jan 29, 2019 at 05:13:16PM +0000, Victor Porton via Digitalmars-d wrote:
> I've successfully implemented it myself:
> 
> ---
> import std.stdio;
> 
> mixin template Cached(string name, string baseName = '_' ~ name) {
>     mixin("private typeof(" ~ baseName ~ ") " ~ name ~ "Cache;");
>     mixin("private bool " ~ name ~ "IsCached = false;");
>     mixin("@property typeof(" ~ baseName ~ ") " ~ name ~ "() {\n" ~
>           "if (" ~ name ~ "IsCached" ~ ") return " ~ name ~ "Cache;\n" ~
>           name ~ "IsCached = true;\n" ~
>           "return " ~ name ~ "Cache = " ~ baseName ~ ";\n" ~
>           '}');
> }
> 
> struct C {
>     @property int _f() { writeln("Got!"); return 2; }
>     mixin Cached!"f";
> }
> 
> void main(string[] args)
> {
>     C x;
>     writeln(x.f);
>     writeln(x.f);
> }
> ---
> 
> I think, we should add this to the standard library. What do you think?

You could have just used std.typecons.Nullable instead of reimplementing it yourself:

	private Nullable!T _myField;
	@property T myField() {
		if (_myField.isNull)
			_myField = ...; // initialize it here
		return _myField;
	}


T

-- 
Elegant or ugly code as well as fine or rude sentences have something in common: they don't depend on the language. -- Luca De Vitis
January 29, 2019
On Tuesday, 29 January 2019 at 18:00:36 UTC, H. S. Teoh wrote:
> You could have just used std.typecons.Nullable instead of reimplementing it yourself:
>
> 	private Nullable!T _myField;
> 	@property T myField() {
> 		if (_myField.isNull)
> 			_myField = ...; // initialize it here
> 		return _myField;
> 	}

I know, but how it is better than my code?