prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  `ifelse` should behave like a ternary expression
  Currently, our conditional `ifelse` operator just sets dependencies in a particular way, but always returns `None`.  It would feel much more natural if it returned a task object whose value at runtime behaved like a standard `x = condition ? if_true : if_false` expression
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/prefect/tasks/control_flow/conditional.py`
  Content:
  ```
  1 from typing import Any, Dict
  2 
  3 import prefect
  4 from prefect import Task
  5 from prefect.engine import signals
  6 
  7 __all__ = ["switch", "ifelse"]
  8 
  9 
  10 class Merge(Task):
  11     def __init__(self, **kwargs) -> None:
  12         if kwargs.setdefault("skip_on_upstream_skip", False):
  13             raise ValueError("Merge tasks must have `skip_on_upstream_skip=False`.")
  14         kwargs.setdefault("trigger", prefect.triggers.not_all_skipped)
  15         super().__init__(**kwargs)
  16 
  17     def run(self, **task_results: Any) -> Any:
  18         return next(
  19             (v for k, v in sorted(task_results.items()) if v is not None), None,
  20         )
  21 
  22 
  23 class CompareValue(Task):
  24     """
  25     This task stores a `value` at initialization and compares it to a `value` received at runtime.
  26     If the values don't match, it raises a SKIP exception.
  27 
  28     Args:
  29         - value (Any): the value this task will attempt to match when it runs
  30         - **kwargs: keyword arguments for the Task
  31     """
  32 
  33     def __init__(self, value: Any, **kwargs: Any):
  34         self.value = value
  35         kwargs.setdefault("name", 'CompareValue: "{}"'.format(value))
  36         super().__init__(**kwargs)
  37 
  38     def run(self, value: Any) -> None:
  39         """
  40         Raises a SKIP signal if the passed value does not match the task's match value;
  41         succeeds silently otherwise.
  42 
  43         Args:
  44             - value (Any): the value that will be matched against the task's value.
  45         """
  46         if value != self.value:
  47             raise signals.SKIP(
  48                 'Provided value "{}" did not match "{}"'.format(value, self.value)
  49             )
  50 
  51 
  52 def switch(condition: Task, cases: Dict[Any, Task]) -> None:
  53     """
  54     Adds a SWITCH to a workflow.
  55 
  56     The condition task is evaluated and the result is compared to the keys of the cases
  57     dictionary. The task corresponding to the matching key is run; all other tasks are
  58     skipped. Any tasks downstream of the skipped tasks are also skipped unless they set
  59     `skip_on_upstream_skip=False`.
  60 
  61     Example:
  62     ```python
  63     @task
  64     def condition():
  65         return "b"    # returning 'b' will take the b_branch
  66 
  67     @task
  68     def a_branch():
  69         return "A Branch"
  70 
  71     @task
  72     def b_branch():
  73         return "B Branch"
  74 
  75     with Flow("switch-flow") as flow:
  76         switch(condition, dict(a=a_branch, b=b_branch))
  77     ```
  78 
  79     Args:
  80         - condition (Task): a task whose result forms the condition for the switch
  81         - cases (Dict[Any, Task]): a dict representing the "case" statements of the switch.
  82             The value of the `condition` task will be compared to the keys of this dict, and
  83             the matching task will be executed.
  84 
  85     Raises:
  86         - PrefectWarning: if any of the tasks in "cases" have upstream dependencies,
  87             then this task will warn that those upstream tasks may run whether or not the switch condition matches their branch. The most common cause of this
  88             is passing a list of tasks as one of the cases, which adds the `List` task
  89             to the switch condition but leaves the tasks themselves upstream.
  90     """
  91 
  92     with prefect.tags("switch"):
  93         for value, task in cases.items():
  94             task = prefect.utilities.tasks.as_task(task)
  95             match_condition = CompareValue(value=value).bind(value=condition)
  96             task.set_dependencies(upstream_tasks=[match_condition])
  97 
  98 
  99 def ifelse(condition: Task, true_task: Task, false_task: Task) -> None:
  100     """
  101     Builds a conditional branch into a workflow.
  102 
  103     If the condition evaluates True(ish), the true_task will run. If it
  104     evaluates False(ish), the false_task will run. The task doesn't run is Skipped, as are
  105     all downstream tasks that don't set `skip_on_upstream_skip=False`.
  106 
  107     Args:
  108         - condition (Task): a task whose boolean result forms the condition for the ifelse
  109         - true_task (Task): a task that will be executed if the condition is True
  110         - false_task (Task): a task that will be executed if the condition is False
  111     """
  112 
  113     @prefect.task
  114     def as_bool(x):
  115         return bool(x)
  116 
  117     switch(condition=as_bool(condition), cases={True: true_task, False: false_task})
  118 
  119 
  120 def merge(*tasks: Task) -> Task:
  121     """
  122     Merges conditional branches back together.
  123 
  124     A conditional branch in a flow results in one or more tasks proceeding and one or
  125     more tasks skipping. It is often convenient to merge those branches back into a
  126     single result. This function is a simple way to achieve that goal. By default this
  127     task will skip if all its upstream dependencies are also skipped.
  128 
  129     The merge will return the first real result it encounters, or `None`. If multiple
  130     tasks might return a result, group them with a list.
  131 
  132     Example:
  133         ```python
  134         with Flow("My Flow"):
  135             true_branch = ActionIfTrue()
  136             false_branch = ActionIfFalse()
  137             ifelse(CheckCondition(), true_branch, false_branch)
  138 
  139             merged_result = merge(true_branch, false_branch)
  140         ```
  141 
  142     Args:
  143         - *tasks (Task): tasks whose results should be merged into a single result. The tasks are
  144             assumed to all sit downstream of different `switch` branches, such that only
  145             one of them will contain a result and the others will all be skipped.
  146 
  147     Returns:
  148         - Task: a Task representing the merged result.
  149 
  150     """
  151     return Merge().bind(**{"task_{}".format(i + 1): t for i, t in enumerate(tasks)})
  152
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/prefect/tasks/control_flow/conditional.py b/src/prefect/tasks/control_flow/conditional.py
  --- a/src/prefect/tasks/control_flow/conditional.py
  +++ b/src/prefect/tasks/control_flow/conditional.py
  @@ -82,11 +82,16 @@
               The value of the `condition` task will be compared to the keys of this dict, and
               the matching task will be executed.
   
  +    Returns:
  +        - Task: a task whose result is the output from the task executed by this switch
  +
       Raises:
           - PrefectWarning: if any of the tasks in "cases" have upstream dependencies,
  -            then this task will warn that those upstream tasks may run whether or not the switch condition matches their branch. The most common cause of this
  -            is passing a list of tasks as one of the cases, which adds the `List` task
  -            to the switch condition but leaves the tasks themselves upstream.
  +            then this task will warn that those upstream tasks may run whether
  +            or not the switch condition matches their branch. The most common
  +            cause of this is passing a list of tasks as one of the cases, which
  +            adds the `List` task to the switch condition but leaves the tasks
  +            themselves upstream.
       """
   
       with prefect.tags("switch"):
  @@ -94,6 +99,7 @@
               task = prefect.utilities.tasks.as_task(task)
               match_condition = CompareValue(value=value).bind(value=condition)
               task.set_dependencies(upstream_tasks=[match_condition])
  +        return merge(*cases.values())
   
   
   def ifelse(condition: Task, true_task: Task, false_task: Task) -> None:
  @@ -101,20 +107,26 @@
       Builds a conditional branch into a workflow.
   
       If the condition evaluates True(ish), the true_task will run. If it
  -    evaluates False(ish), the false_task will run. The task doesn't run is Skipped, as are
  -    all downstream tasks that don't set `skip_on_upstream_skip=False`.
  +    evaluates False(ish), the false_task will run. The task that doesn't run is
  +    Skipped, as are all downstream tasks that don't set
  +    `skip_on_upstream_skip=False`.
   
       Args:
           - condition (Task): a task whose boolean result forms the condition for the ifelse
           - true_task (Task): a task that will be executed if the condition is True
           - false_task (Task): a task that will be executed if the condition is False
  +
  +    Returns:
  +        - Task: a task whose result is the output from the task executed by this ifelse
       """
   
       @prefect.task
       def as_bool(x):
           return bool(x)
   
  -    switch(condition=as_bool(condition), cases={True: true_task, False: false_task})
  +    return switch(
  +        condition=as_bool(condition), cases={True: true_task, False: false_task}
  +    )
   
   
   def merge(*tasks: Task) -> Task:
  
verification_info: {"golden_diff": "diff --git a/src/prefect/tasks/control_flow/conditional.py b/src/prefect/tasks/control_flow/conditional.py\n--- a/src/prefect/tasks/control_flow/conditional.py\n+++ b/src/prefect/tasks/control_flow/conditional.py\n@@ -82,11 +82,16 @@\n             The value of the `condition` task will be compared to the keys of this dict, and\n             the matching task will be executed.\n \n+    Returns:\n+        - Task: a task whose result is the output from the task executed by this switch\n+\n     Raises:\n         - PrefectWarning: if any of the tasks in \"cases\" have upstream dependencies,\n-            then this task will warn that those upstream tasks may run whether or not the switch condition matches their branch. The most common cause of this\n-            is passing a list of tasks as one of the cases, which adds the `List` task\n-            to the switch condition but leaves the tasks themselves upstream.\n+            then this task will warn that those upstream tasks may run whether\n+            or not the switch condition matches their branch. The most common\n+            cause of this is passing a list of tasks as one of the cases, which\n+            adds the `List` task to the switch condition but leaves the tasks\n+            themselves upstream.\n     \"\"\"\n \n     with prefect.tags(\"switch\"):\n@@ -94,6 +99,7 @@\n             task = prefect.utilities.tasks.as_task(task)\n             match_condition = CompareValue(value=value).bind(value=condition)\n             task.set_dependencies(upstream_tasks=[match_condition])\n+        return merge(*cases.values())\n \n \n def ifelse(condition: Task, true_task: Task, false_task: Task) -> None:\n@@ -101,20 +107,26 @@\n     Builds a conditional branch into a workflow.\n \n     If the condition evaluates True(ish), the true_task will run. If it\n-    evaluates False(ish), the false_task will run. The task doesn't run is Skipped, as are\n-    all downstream tasks that don't set `skip_on_upstream_skip=False`.\n+    evaluates False(ish), the false_task will run. The task that doesn't run is\n+    Skipped, as are all downstream tasks that don't set\n+    `skip_on_upstream_skip=False`.\n \n     Args:\n         - condition (Task): a task whose boolean result forms the condition for the ifelse\n         - true_task (Task): a task that will be executed if the condition is True\n         - false_task (Task): a task that will be executed if the condition is False\n+\n+    Returns:\n+        - Task: a task whose result is the output from the task executed by this ifelse\n     \"\"\"\n \n     @prefect.task\n     def as_bool(x):\n         return bool(x)\n \n-    switch(condition=as_bool(condition), cases={True: true_task, False: false_task})\n+    return switch(\n+        condition=as_bool(condition), cases={True: true_task, False: false_task}\n+    )\n \n \n def merge(*tasks: Task) -> Task:\n", "issue": "`ifelse` should behave like a ternary expression\nCurrently, our conditional `ifelse` operator just sets dependencies in a particular way, but always returns `None`.  It would feel much more natural if it returned a task object whose value at runtime behaved like a standard `x = condition ? if_true : if_false` expression\n", "before_files": [{"content": "from typing import Any, Dict\n\nimport prefect\nfrom prefect import Task\nfrom prefect.engine import signals\n\n__all__ = [\"switch\", \"ifelse\"]\n\n\nclass Merge(Task):\n    def __init__(self, **kwargs) -> None:\n        if kwargs.setdefault(\"skip_on_upstream_skip\", False):\n            raise ValueError(\"Merge tasks must have `skip_on_upstream_skip=False`.\")\n        kwargs.setdefault(\"trigger\", prefect.triggers.not_all_skipped)\n        super().__init__(**kwargs)\n\n    def run(self, **task_results: Any) -> Any:\n        return next(\n            (v for k, v in sorted(task_results.items()) if v is not None), None,\n        )\n\n\nclass CompareValue(Task):\n    \"\"\"\n    This task stores a `value` at initialization and compares it to a `value` received at runtime.\n    If the values don't match, it raises a SKIP exception.\n\n    Args:\n        - value (Any): the value this task will attempt to match when it runs\n        - **kwargs: keyword arguments for the Task\n    \"\"\"\n\n    def __init__(self, value: Any, **kwargs: Any):\n        self.value = value\n        kwargs.setdefault(\"name\", 'CompareValue: \"{}\"'.format(value))\n        super().__init__(**kwargs)\n\n    def run(self, value: Any) -> None:\n        \"\"\"\n        Raises a SKIP signal if the passed value does not match the task's match value;\n        succeeds silently otherwise.\n\n        Args:\n            - value (Any): the value that will be matched against the task's value.\n        \"\"\"\n        if value != self.value:\n            raise signals.SKIP(\n                'Provided value \"{}\" did not match \"{}\"'.format(value, self.value)\n            )\n\n\ndef switch(condition: Task, cases: Dict[Any, Task]) -> None:\n    \"\"\"\n    Adds a SWITCH to a workflow.\n\n    The condition task is evaluated and the result is compared to the keys of the cases\n    dictionary. The task corresponding to the matching key is run; all other tasks are\n    skipped. Any tasks downstream of the skipped tasks are also skipped unless they set\n    `skip_on_upstream_skip=False`.\n\n    Example:\n    ```python\n    @task\n    def condition():\n        return \"b\"    # returning 'b' will take the b_branch\n\n    @task\n    def a_branch():\n        return \"A Branch\"\n\n    @task\n    def b_branch():\n        return \"B Branch\"\n\n    with Flow(\"switch-flow\") as flow:\n        switch(condition, dict(a=a_branch, b=b_branch))\n    ```\n\n    Args:\n        - condition (Task): a task whose result forms the condition for the switch\n        - cases (Dict[Any, Task]): a dict representing the \"case\" statements of the switch.\n            The value of the `condition` task will be compared to the keys of this dict, and\n            the matching task will be executed.\n\n    Raises:\n        - PrefectWarning: if any of the tasks in \"cases\" have upstream dependencies,\n            then this task will warn that those upstream tasks may run whether or not the switch condition matches their branch. The most common cause of this\n            is passing a list of tasks as one of the cases, which adds the `List` task\n            to the switch condition but leaves the tasks themselves upstream.\n    \"\"\"\n\n    with prefect.tags(\"switch\"):\n        for value, task in cases.items():\n            task = prefect.utilities.tasks.as_task(task)\n            match_condition = CompareValue(value=value).bind(value=condition)\n            task.set_dependencies(upstream_tasks=[match_condition])\n\n\ndef ifelse(condition: Task, true_task: Task, false_task: Task) -> None:\n    \"\"\"\n    Builds a conditional branch into a workflow.\n\n    If the condition evaluates True(ish), the true_task will run. If it\n    evaluates False(ish), the false_task will run. The task doesn't run is Skipped, as are\n    all downstream tasks that don't set `skip_on_upstream_skip=False`.\n\n    Args:\n        - condition (Task): a task whose boolean result forms the condition for the ifelse\n        - true_task (Task): a task that will be executed if the condition is True\n        - false_task (Task): a task that will be executed if the condition is False\n    \"\"\"\n\n    @prefect.task\n    def as_bool(x):\n        return bool(x)\n\n    switch(condition=as_bool(condition), cases={True: true_task, False: false_task})\n\n\ndef merge(*tasks: Task) -> Task:\n    \"\"\"\n    Merges conditional branches back together.\n\n    A conditional branch in a flow results in one or more tasks proceeding and one or\n    more tasks skipping. It is often convenient to merge those branches back into a\n    single result. This function is a simple way to achieve that goal. By default this\n    task will skip if all its upstream dependencies are also skipped.\n\n    The merge will return the first real result it encounters, or `None`. If multiple\n    tasks might return a result, group them with a list.\n\n    Example:\n        ```python\n        with Flow(\"My Flow\"):\n            true_branch = ActionIfTrue()\n            false_branch = ActionIfFalse()\n            ifelse(CheckCondition(), true_branch, false_branch)\n\n            merged_result = merge(true_branch, false_branch)\n        ```\n\n    Args:\n        - *tasks (Task): tasks whose results should be merged into a single result. The tasks are\n            assumed to all sit downstream of different `switch` branches, such that only\n            one of them will contain a result and the others will all be skipped.\n\n    Returns:\n        - Task: a Task representing the merged result.\n\n    \"\"\"\n    return Merge().bind(**{\"task_{}\".format(i + 1): t for i, t in enumerate(tasks)})\n", "path": "src/prefect/tasks/control_flow/conditional.py"}], "after_files": [{"content": "from typing import Any, Dict\n\nimport prefect\nfrom prefect import Task\nfrom prefect.engine import signals\n\n__all__ = [\"switch\", \"ifelse\"]\n\n\nclass Merge(Task):\n    def __init__(self, **kwargs) -> None:\n        if kwargs.setdefault(\"skip_on_upstream_skip\", False):\n            raise ValueError(\"Merge tasks must have `skip_on_upstream_skip=False`.\")\n        kwargs.setdefault(\"trigger\", prefect.triggers.not_all_skipped)\n        super().__init__(**kwargs)\n\n    def run(self, **task_results: Any) -> Any:\n        return next(\n            (v for k, v in sorted(task_results.items()) if v is not None), None,\n        )\n\n\nclass CompareValue(Task):\n    \"\"\"\n    This task stores a `value` at initialization and compares it to a `value` received at runtime.\n    If the values don't match, it raises a SKIP exception.\n\n    Args:\n        - value (Any): the value this task will attempt to match when it runs\n        - **kwargs: keyword arguments for the Task\n    \"\"\"\n\n    def __init__(self, value: Any, **kwargs: Any):\n        self.value = value\n        kwargs.setdefault(\"name\", 'CompareValue: \"{}\"'.format(value))\n        super().__init__(**kwargs)\n\n    def run(self, value: Any) -> None:\n        \"\"\"\n        Raises a SKIP signal if the passed value does not match the task's match value;\n        succeeds silently otherwise.\n\n        Args:\n            - value (Any): the value that will be matched against the task's value.\n        \"\"\"\n        if value != self.value:\n            raise signals.SKIP(\n                'Provided value \"{}\" did not match \"{}\"'.format(value, self.value)\n            )\n\n\ndef switch(condition: Task, cases: Dict[Any, Task]) -> None:\n    \"\"\"\n    Adds a SWITCH to a workflow.\n\n    The condition task is evaluated and the result is compared to the keys of the cases\n    dictionary. The task corresponding to the matching key is run; all other tasks are\n    skipped. Any tasks downstream of the skipped tasks are also skipped unless they set\n    `skip_on_upstream_skip=False`.\n\n    Example:\n    ```python\n    @task\n    def condition():\n        return \"b\"    # returning 'b' will take the b_branch\n\n    @task\n    def a_branch():\n        return \"A Branch\"\n\n    @task\n    def b_branch():\n        return \"B Branch\"\n\n    with Flow(\"switch-flow\") as flow:\n        switch(condition, dict(a=a_branch, b=b_branch))\n    ```\n\n    Args:\n        - condition (Task): a task whose result forms the condition for the switch\n        - cases (Dict[Any, Task]): a dict representing the \"case\" statements of the switch.\n            The value of the `condition` task will be compared to the keys of this dict, and\n            the matching task will be executed.\n\n    Returns:\n        - Task: a task whose result is the output from the task executed by this switch\n\n    Raises:\n        - PrefectWarning: if any of the tasks in \"cases\" have upstream dependencies,\n            then this task will warn that those upstream tasks may run whether\n            or not the switch condition matches their branch. The most common\n            cause of this is passing a list of tasks as one of the cases, which\n            adds the `List` task to the switch condition but leaves the tasks\n            themselves upstream.\n    \"\"\"\n\n    with prefect.tags(\"switch\"):\n        for value, task in cases.items():\n            task = prefect.utilities.tasks.as_task(task)\n            match_condition = CompareValue(value=value).bind(value=condition)\n            task.set_dependencies(upstream_tasks=[match_condition])\n        return merge(*cases.values())\n\n\ndef ifelse(condition: Task, true_task: Task, false_task: Task) -> None:\n    \"\"\"\n    Builds a conditional branch into a workflow.\n\n    If the condition evaluates True(ish), the true_task will run. If it\n    evaluates False(ish), the false_task will run. The task that doesn't run is\n    Skipped, as are all downstream tasks that don't set\n    `skip_on_upstream_skip=False`.\n\n    Args:\n        - condition (Task): a task whose boolean result forms the condition for the ifelse\n        - true_task (Task): a task that will be executed if the condition is True\n        - false_task (Task): a task that will be executed if the condition is False\n\n    Returns:\n        - Task: a task whose result is the output from the task executed by this ifelse\n    \"\"\"\n\n    @prefect.task\n    def as_bool(x):\n        return bool(x)\n\n    return switch(\n        condition=as_bool(condition), cases={True: true_task, False: false_task}\n    )\n\n\ndef merge(*tasks: Task) -> Task:\n    \"\"\"\n    Merges conditional branches back together.\n\n    A conditional branch in a flow results in one or more tasks proceeding and one or\n    more tasks skipping. It is often convenient to merge those branches back into a\n    single result. This function is a simple way to achieve that goal. By default this\n    task will skip if all its upstream dependencies are also skipped.\n\n    The merge will return the first real result it encounters, or `None`. If multiple\n    tasks might return a result, group them with a list.\n\n    Example:\n        ```python\n        with Flow(\"My Flow\"):\n            true_branch = ActionIfTrue()\n            false_branch = ActionIfFalse()\n            ifelse(CheckCondition(), true_branch, false_branch)\n\n            merged_result = merge(true_branch, false_branch)\n        ```\n\n    Args:\n        - *tasks (Task): tasks whose results should be merged into a single result. The tasks are\n            assumed to all sit downstream of different `switch` branches, such that only\n            one of them will contain a result and the others will all be skipped.\n\n    Returns:\n        - Task: a Task representing the merged result.\n\n    \"\"\"\n    return Merge().bind(**{\"task_{}\".format(i + 1): t for i, t in enumerate(tasks)})\n", "path": "src/prefect/tasks/control_flow/conditional.py"}]}