This is very much implementation dependent. And I do not have a big opinion
here as I certainly haven’t spent enough time to have one. I am just
considering functionality from user’s perspective for the time being.
> Let's tackle just this one part for a moment. What does "ensure_eval"
> do? Evaluate a proxy object but not evaluate anything else?
In case of the library I used, it would look something like:
def ensure_eval(x):
if isisnstance(x, Proxy) and x.unevaulated:
x.evaluate()
return x
> This should always succeed, right? Well, what if x is itself a Proxy
> object? How does it know not to reevaluate it?
Not necessarily. I mean, yes, but only if deferred evaluation is done by
actually replacing value in the namespace dictionary. In case of this example,
where this specific package is used, it is not so and is not intended to be so.
When operation is performed, the value is evaluated and returned, but it
remains proxy object. So if lazy is nested, the whole nesting is evaluated on
first operation which needs its value.
I see this one as “decision to be made” as opposed to “reason why it’s not
working”.
I am not sure about the “right” approach here. Actually replacing deferred
object with a value does sound invasive, although given there was a way to do
it elegantly and without loss in performance, it seems to be more robust and
eliminates maintenance of proxy object.
So the big question is, which of the 2 approaches to take:
1) Implementing a robust proxy object.
Less depth more breadth - ensuring proxy works with all objects / coming up
with protocols, which have to be implemented for non-standard types to be
compatible.
In this case both of assertions will and should fail, although `assert y is
y_` will always pass.
Example from library:
obj = Proxy(lambda: 1)
obj2 = Proxy(lambda: obj)
obj is obj2 # False
print(obj == obj2) # True
2) Replacing deferred evaluation with it’s value.
in this case, a fair bit of low level decisions such as the one you
indicated would have to be made, a lot of deep strings to pull
In this case, it very much depends how “is”, “type” and other `things`
behave with deferred objects. So if `x` is a proxy, and ‘is’ treats proxy
object and not it’s value (which is reasonable), then assertions will and
should fail. However, unraveling the whole stack on first evaluation does
simplify things a bit.Then ` y_ = ensure_eval(y)` in your example is a
redundant line. In practice, if deferred evaluation is used, one would need to:
`assert ensure_eval(x) is ensure_eval(y)`. Also, looking at deferred eval RST
doc, the suggested mechanics are that expression is evaluated if “later” is not
re-called. So in theory, it might be reasonable to have `x = later expr()
<equiv> x = later later later expr()`. Instead of evaluating the whole stack,
just not allowing it to grow in the first place. Then builtin `ensure_eval` is
then straight forward single operation at C level, which would mostly be used
on low level checks, such as asserts in your examples. It could even have its
syntax instead of builtin function, given there are only 2 entry points
(definition of deferred & ensuring it’s evaluation). E.g.
def expr():
print('Evaluating')
return 1
a = `expr()`
b = `a` # carry over lazy, but it's a new object at C level
assert a is b # False
assert !a is !b # True
assert a is b # True
> On 21 Jul 2023, at 08:46, Chris Angelico <[email protected]> wrote:
>
> On Fri, 21 Jul 2023 at 11:08, Dom Grigonis <[email protected]> wrote:
>> Also, can't find a way to ONLY force evaluation without any additional
>> operations in this specific library. A simple callable which evaluates if
>> unevaluated & returns would do. Then:
>>
>> def IF(condition, when_true, when_false):
>> if condition:
>> return ensure_eval(when_true)
>> else:
>> return ensure_eval(when_false)
>>
>> Controls evaluation if deferred objects are provided, but can also be used
>> with `normal` values.
>>
>
> Let's tackle just this one part for a moment. What does "ensure_eval"
> do? Evaluate a proxy object but not evaluate anything else? That seems
> simple, but might very well be straight-up wrong. Consider:
>
> def test_proxy(x):
> x_ = Proxy(x)
> y = ensure_eval(x_)
> y_ = ensure_eval(y)
> assert x is y
> assert x is y_
>
> This should always succeed, right? Well, what if x is itself a Proxy
> object? How does it know not to reevaluate it?
>
> ChrisA
> _______________________________________________
> Python-ideas mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/[email protected]/message/GTCRUPQOFP63VA2T2N7BVBO6JKR3D7I6/
> Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/CREQ6ANIJKVHLMYTLWUQCNHTII36PLAT/
Code of Conduct: http://python.org/psf/codeofconduct/