Skip to content

Commit 9db8d10

Browse files
committed
Add a design topic page on lazy vs. eager implementations
Follow-up to data-apisgh-652, which added notes to the specifications for `__bool__` & co on this topic.
1 parent 267a41c commit 9db8d10

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

Diff for: spec/draft/design_topics/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Design topics & constraints
77

88
copies_views_and_mutation
99
data_dependent_output_shapes
10+
lazy_eager
1011
data_interchange
1112
device_support
1213
static_typing

Diff for: spec/draft/design_topics/lazy_eager.rst

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
.. _lazy-eager:
2+
3+
Lazy vs. eager execution
4+
========================
5+
6+
While the execution model for implementations is out of scope of this standard, there are a few aspects of lazy (or graph-based) execution as contrasted to eager execution that may have an impact on the prescribed semantics of individual APIs, and will therefore show up in the API specification.
7+
8+
One important difference is data-dependent or value-dependent behavior, as described in :ref:`data-dependent-output-shapes`. Because such behavior is hard to implement, implementers may choose to omit such APIs from their library.
9+
10+
Another difference is when the Python language itself prescribes that a specific type *must* be returned. For those cases, it is not possible to return a lazy/delayed kind of object to avoid computing a value. This is the case for five dunder methods: `__bool__`, `__int__`, `__float__`, `__complex__` and `__index__`. Each implementation has only two choices when one of these methods is called:
11+
12+
1. Compute a value of the required type (a Python scalar of type `bool`, `int`, `float` or `complex`), or
13+
2. Raise an exception.
14+
15+
When an implementation is 100% lazy, for example when it serializes a computation graph, computing the value is not possible and hence such an implementation has no choice but to raise an exception. For a "mostly lazy" implementation, it may make sense to trigger execution instead - but it is not required to, both choices are valid.
16+
17+
A common code construct where this happens is conditional logic, e.g.::
18+
19+
vals = compute_something()
20+
if all(vals):
21+
# The if-statement will make Python call the __bool__ method
22+
# on the result of `all(vals)`.
23+
do_something_else()

0 commit comments

Comments
 (0)