New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New conditional api #2443
New conditional api #2443
Conversation
This adds two new control flow constructs: - `case`: for creating conditional branches in a flow - `Variable`: for merging conditional branches back together These do similar things to `switch` and `merge`, but should hopefully be easier to read. Still needs tests and docs, just getting a WIP up for comments.
And an example: from prefect.tasks.control_flow.case import case, Variable
from prefect import task, Flow
@task
def some_condition():
return True
@task
def other_condition():
return True
@task
def do_a():
print("Doing a")
return 1
@task
def do_b():
print("Doing b")
return 2
@task
def do_c(a, b):
print("Doing c")
return a + b
@task
def do_d():
print("Doing d")
return 1
@task
def do_e(d):
print("Doing e")
return d + 1
def example_3():
"""Same example logic without prefect"""
if some_condition():
if other_condition():
a = do_a()
else:
a = do_c(1, 2)
b = do_b()
do_c(a, b)
else:
d = do_d()
do_e(d)
with Flow("example-3") as flow:
cond = some_condition()
with case(cond, True):
cond2 = other_condition()
a = Variable(name="a")
with case(cond2, True):
a.set(do_a())
with case(cond2, False):
a.set(do_c(1, 2))
b = do_b()
do_c(a, b)
with case(cond, False):
d = do_d()
do_e(d) Results in the following graph: |
See #2381 for the description of the semantics. A few naming questions:
And a few semantic question:
@task
def inc(x):
return x + 1
v = Variable(name="a")
a.set(1)
b = inc(a)
a.set(2) In this case
with Flow("example-3") as flow:
cond = some_condition()
with case(cond, True):
cond2 = other_condition()
with case(cond2, True):
a1 = do_a()
with case(cond2, False):
a2 = do_c(1, 2)
a = merge(a1, a2)
b = do_b()
do_c(a, b)
with case(cond, False):
d = do_d()
do_e(d) |
Thinking about this a bit more, I think I'm leaning slightly towards dropping |
@jcrist i really love this syntax - I think it removes significant complexity, especially for users who just want to gate a small number of conditional tasks. My opinion is to drop the Variable entirely; on the one hand I’m super impressed you solved the problem of working with a deferred multi-assigned variable, but I worry the nuance of applying variables correctly will be overshadowed by the additional burden of explaining them, why they differ from parameters, etc., especially because they add a lot of machinery to replace a relatively small merge op. Therefore I think a great example in our documentation of how to merge two conditional branches will provide a good solution with lower maintenance overhead. |
Ok, I've updated to remove
|
@jcrist here's my 2¢ on your Qs:
|
Awesome this is great; to your points:
|
Ok, given the above comments I, I think I'm going to keep things as they are. I've added a changelog entry, I believe this is now ready for merge. |
This adds two new control flow constructs:
case
: for creating conditional branches in a flowVariable
: for merging conditional branches back togetherThese do similar things to
switch
andmerge
, but should hopefully beeasier to read.
Still needs tests and docs, just getting a WIP up for comments.
Fixes #2381
CHANGELOG.md
(if appropriate)docs/outline.toml
for API reference docs (if appropriate)