www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Cached property (translate Python -> D)

reply Victor Porton <porton narod.ru> writes:
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
---
Jan 29 2019
next sibling parent reply Daniel Kozak <kozzi11 gmail.com> writes:
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
 ---
Jan 29 2019
parent Victor Porton <porton narod.ru> writes:
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; }
Jan 29 2019
prev sibling next sibling parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
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!
Jan 29 2019
prev sibling parent reply Victor Porton <porton narod.ru> writes:
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?
Jan 29 2019
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Jan 29 2019
parent Victor Porton <porton narod.ru> writes:
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?
Jan 29 2019