Skip to content
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

Routers and Selectors. Part 2 switch #804

Open
emil14 opened this issue Dec 14, 2024 · 0 comments
Open

Routers and Selectors. Part 2 switch #804

emil14 opened this issue Dec 14, 2024 · 0 comments
Assignees

Comments

@emil14
Copy link
Collaborator

emil14 commented Dec 14, 2024

Previous part - #802

Switch

Basic

Switch is a more advanced version of If that can handle all data types, not just booleans, and can have as many branches as needed.

data_sender -> switch {
    cond_sender1 -> then_receiver1
    cond_sender2 -> then_receiver2
    ...
    _ -> default_then_receiver
}

Example

:number -> switch {
    0 -> restart
    42 -> answer_the_universe
    _ -> panic
}

Switch can emulate all possible forms of If. Here is the simplest example:

If syntax should is preffered

cond_sender -> switch {
    true -> then_receiver
    _ -> else_receiver
}

Switch-True

This is not a special form but rather a pattern that the switch can implement. By sending a true literal as a condition, the switch will execute the first branch that evaluates to true. Example:

true -> switch {
    (:user.role == 'admin') -> show_metrics
    (:user.age > 18) -> greet_user
    _ -> panic
}

One Branch, Many Senders and Receivers

Just like if, the switch statement supports multiple receivers on a single branch, functioning as a fan-out.

data_sender -> switch {
    cond_sender1 -> [then_sender1, then_receiver2]
    ...
}

However, switch also allows multiple senders on the same branch. In this case, they are handled like a union. The switch compares the data message with every condition on a branch before moving to the next one. As soon as a match is found, it selects the branch and sends the data message further downstream.

data_sender -> switch {
    [cond_sender1, cond_sender2] -> then_receiver1
    ...
}

It might not be immediately clear that multiple condition senders are not fan-in, as the syntax might suggest. However, introducing a different syntax for this use-case would be overwhelming, and having fan-in semantics here does not make sense.

Just like with if, all features of switch, including those described below, can be combined in various ways. For example, it is possible to have both multiple condition senders and multiple branch receivers simultaneously.

data_sender -> switch {
    [cond_sender1, cond_sender2] -> then_receiver1
    cond_sender3 -> [then_sender2, then_receiver3]
    [cond_sender4, cond_sender4] -> [then_sender4, then_receiver5]
    ...
}

With Final Receiver

Similar to if, the switch can have a final receiver connected to its body. Just like if, it receives a message from the data_sender after the selected receiver(s) have received their messages.

data_sender -> switch {
    cond_sender1 -> then_receiver1
    cond_sender2 -> then_receiver2
    ...
    _ -> default_then_sender
} -> receiver

With Extra Inport

Similarly to if, the switch can route one message based on another:

data_sender -> switch cond_sender {
    cond_branch_sender1 -> then_receiver1
    cond_branch_sender2 -> then_receiver2
    ...
    _ -> default_receiver
} -> final_receiver

In that case, the final receiver will receive a message of type SwitchResult<T, Y>, where data is the message from the data sender and cond is the message from the selected condition branch sender.

{
    data T
    cond Y
}

Selector

Finally, similar to if and like all routers, the switch has a "selector-mode" where it not only selects a branch to send but also selects a message to send. This is a natural extension of its previous form "with extra inport":

cond_sender -> switch {
    cond_sender1: data_sender1 -> then_receiver1
    cond_sender2: data_sender2 -> then_receiver2
    ...
    _ -> default_then_sender
} -> receiver

Multiple condition senders and multiple branch receivers are also supported. This means you can have multiple conditions determining which branch to take, and each branch can have multiple receivers.

cond_sender -> switch {
    [cond_sender1, cond_sender2]: data_sender1 -> then_receiver1
    cond_sender3: data_sender2 -> [then_receiver2, then_receiver3]
    ...
    _ -> default_then_sender
} -> receiver

Notice that multiple data senders are not supported. If you think about it, it will actually make sense. We select a message and direction based on the condition, so we need to select a single message to send.

The more parts a switch has, the more latency it can have. It must wait for the condition sender, all condition and data branch senders, wait for the selected receivers, and finally wait for the final receiver, before receiving the next message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant