Lazy evaluated

Discussion in 'Python' started by Habibutsu, Mar 28, 2013.

  1. Habibutsu

    Habibutsu Guest

    For example, we have following code:

    01| def foo():
    02| return 1
    03|
    04| value = foo()
    05|
    06| if value == 1:
    07| print value,"- equal 1"
    08|
    09| if isinstance(value, int):
    10| print value,"- is int"
    11| else:
    12| print value,"- is not int"

    Task is to create lazy evaluation for function 'foo'.
    For decision this task we create special function 'lazy' which turn
    original function into a lazy evaluated function by means of creating
    proxy object that evaluated value if needed. We add following code:

    01| def lazy(func):
    02|
    03| class ProxyLazy(object):
    04| _result_value = None
    05|
    06| @property
    07| def result_value(self):
    08| if self._result_value is not None:
    09| return self._result_value
    10| self._result_value = self.func(*self.args, **self.kw)
    11| return self._result_value
    12|
    13| def __str__(self):
    14| return str(self.result_value)
    15|
    16| def __cmp__(self, other):
    17| return cmp(self.result_value, other)
    18|
    19| # and other __unicode__, __eq__, __ne__ and so on
    20|
    21| def wrapper(*args, **kw):
    22| proxy = ProxyLazy()
    23| proxy.func = func
    24| proxy.args = args
    25| proxy.kw = kw
    26| return proxy
    27|
    28| return wrapper
    29|
    30| lazy_foo = lazy(foo)
    31| value = lazy_foo()

    Unfortunately, this method not allow to use 'isinstance' for check type.
    We can create other variant of function 'lazy' is 'lazy_promise' in
    which additional parameter will be passed with type of result value.
    After we can create 'LazyMetaClass' with helping of which will be
    created 'ProxyLazy'

    01| def lazy_promise(func, resultclass):
    02|
    03| class LazyMetaClass(type):
    04| def __new__(cls, name, bases, attrs):
    05| return super(LazyMetaClass, cls).__new__(cls, name,
    (resultclass,), attrs)
    06|
    07| class ProxyLazy(object):
    08| __metaclass__ = LazyMetaClass
    ....
    35| lazy_foo = lazy_promise(foo, int)
    36| value = lazy_foo()

    And everything seems to work, but appear other questions. If original
    function return different types - what to do in this case? Where i am
    wrong? What other way to do that. Was no idea to create keyword 'lazy'
    in Python?

    Thanks
    Habibutsu, Mar 28, 2013
    #1
    1. Advertising

  2. On Thu, 28 Mar 2013 22:37:47 +0300, Habibutsu wrote:

    > For example, we have following code:
    >
    > 01| def foo():
    > 02| return 1
    > 03|
    > 04| value = foo()
    > 05|
    > 06| if value == 1:
    > 07| print value,"- equal 1"
    > 08|
    > 09| if isinstance(value, int):
    > 10| print value,"- is int"
    > 11| else:
    > 12| print value,"- is not int"
    >
    > Task is to create lazy evaluation for function 'foo'. For decision this
    > task we create special function 'lazy' which turn original function into
    > a lazy evaluated function by means of creating proxy object that
    > evaluated value if needed. We add following code:
    >
    >
    > 01| def lazy(func):
    > 02|
    > 03| class ProxyLazy(object):
    > 04| _result_value = None
    > 05|
    > 06| @property
    > 07| def result_value(self):

    [...]


    It is often useful for the reader to copy and paste code blocks like this
    into the interactive interpreter. It is more friendly and useful if you
    paste it in a format that makes that easy (no prompts, no line numbers,
    no blank lines inside classes or functions). Otherwise the reader has to
    copy your code, paste it into an editor, strip out the line numbers and
    blank lines, copy and paste it into the interpreter, and THEN they can
    finally test your code and see what it does.


    > 30| lazy_foo = lazy(foo)
    > 31| value = lazy_foo()
    >
    > Unfortunately, this method not allow to use 'isinstance' for check type.


    Correct. And so it should not, because it value is not an int, it is a
    ProxyLazy object. You cannot use a ProxyLazy object where an int is
    expected:

    py> value + 1
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'ProxyLazy' and 'int'


    so it is inappropriate to claim that value is an int.

    I must admit, I don't understand the value of this "lazy proxy" type you
    have created. You get a proxy like this:

    value = lazy(foo)() # get a lazy proxy
    # much later
    value = value.func() # now safe to use as an int
    print(value + 1)

    What benefit does the lazy proxy give? Why not just do this?


    value = foo() # functions are already a lazy proxy
    # much later
    value = value() # now safe to use as an int
    print(value + 1)


    [...]
    > And everything seems to work, but appear other questions. If original
    > function return different types - what to do in this case? Where i am
    > wrong? What other way to do that. Was no idea to create keyword 'lazy'
    > in Python?


    Why should it be a keyword? Python has very few keywords, and most of
    them are for programming flow control, like "if", "else", "for", "while",
    "pass", etc.




    --
    Steven
    Steven D'Aprano, Mar 29, 2013
    #2
    1. Advertising

  3. Habibutsu

    Habibutsu Guest

    On 03/29/2013 05:40 AM, Steven D'Aprano wrote:
    > On Thu, 28 Mar 2013 22:37:47 +0300, Habibutsu wrote:
    >
    >> For example, we have following code:
    >>
    >> 01| def foo():
    >> 02| return 1
    >> 03|
    >> 04| value = foo()
    >> 05|
    >> 06| if value == 1:
    >> 07| print value,"- equal 1"
    >> 08|
    >> 09| if isinstance(value, int):
    >> 10| print value,"- is int"
    >> 11| else:
    >> 12| print value,"- is not int"
    >>
    >> Task is to create lazy evaluation for function 'foo'. For decision this
    >> task we create special function 'lazy' which turn original function into
    >> a lazy evaluated function by means of creating proxy object that
    >> evaluated value if needed. We add following code:
    >>
    >>
    >> 01| def lazy(func):
    >> 02|
    >> 03| class ProxyLazy(object):
    >> 04| _result_value = None
    >> 05|
    >> 06| @property
    >> 07| def result_value(self):

    > [...]
    >
    >
    > It is often useful for the reader to copy and paste code blocks like this
    > into the interactive interpreter. It is more friendly and useful if you
    > paste it in a format that makes that easy (no prompts, no line numbers,
    > no blank lines inside classes or functions). Otherwise the reader has to
    > copy your code, paste it into an editor, strip out the line numbers and
    > blank lines, copy and paste it into the interpreter, and THEN they can
    > finally test your code and see what it does.
    >

    Previously I not to do it, yesterday decide to experiment. It seemed to
    me more readable if to see in the email-clent. Sorry, I will keep in
    mind in the future.
    >> 30| lazy_foo = lazy(foo)
    >> 31| value = lazy_foo()
    >>
    >> Unfortunately, this method not allow to use 'isinstance' for check type.

    > Correct. And so it should not, because it value is not an int, it is a
    > ProxyLazy object. You cannot use a ProxyLazy object where an int is
    > expected:
    >
    > py> value + 1
    > Traceback (most recent call last):
    > File "<stdin>", line 1, in <module>
    > TypeError: unsupported operand type(s) for +: 'ProxyLazy' and 'int'
    >

    Why not?

    def __add__(self, other):
    return self._result_value + other

    and then
    >>> print value + 1

    2

    > so it is inappropriate to claim that value is an int.


    I can overload all arithmetic operators and get almost really int value,
    but I don't like to write many trivial code.

    > I must admit, I don't understand the value of this "lazy proxy" type you
    > have created. You get a proxy like this:
    >
    > value = lazy(foo)() # get a lazy proxy
    > # much later
    > value = value.func() # now safe to use as an int
    > print(value + 1)
    >
    > What benefit does the lazy proxy give? Why not just do this?

    Because some people like to use "list comprehensions" and other not,
    some people like labmda and other not. Advantage is that I can write
    more expressive code and use different strategies for different cases.
    "value = value.func()" is looks sad while I just need the value.
    >
    > value = foo() # functions are already a lazy proxy
    > # much later
    > value = value() # now safe to use as an int
    > print(value + 1)
    >
    >
    > [...]
    >> And everything seems to work, but appear other questions. If original
    >> function return different types - what to do in this case? Where i am
    >> wrong? What other way to do that. Was no idea to create keyword 'lazy'
    >> in Python?

    > Why should it be a keyword? Python has very few keywords, and most of
    > them are for programming flow control, like "if", "else", "for", "while",
    > "pass", etc.
    >

    Question not in why I can't use exist tools - I can. If i can write code
    without classes that it does not mean that classes need to delete from
    language. Question why in language not present this ability?

    Thanks
    Habibutsu, Mar 29, 2013
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steph
    Replies:
    2
    Views:
    1,639
    heislord5
    May 11, 2011
  2. Jason Wright via .NET 247
    Replies:
    2
    Views:
    659
    Brian W
    Jun 12, 2004
  3. Ken Pu
    Replies:
    3
    Views:
    659
    Steven D'Aprano
    Jan 16, 2009
  4. Boris Borcic
    Replies:
    0
    Views:
    535
    Boris Borcic
    Jan 16, 2009
  5. Boris Borcic
    Replies:
    0
    Views:
    536
    Boris Borcic
    Jan 16, 2009
Loading...

Share This Page