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

Add documentation for select #747

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* [if !](syntax_and_semantics/not.md)
* [unless](syntax_and_semantics/unless.md)
* [case](syntax_and_semantics/case.md)
* [select](syntax_and_semantics/select.md)
* [while](syntax_and_semantics/while.md)
* [break](syntax_and_semantics/break.md)
* [next](syntax_and_semantics/next.md)
Expand Down
53 changes: 53 additions & 0 deletions docs/syntax_and_semantics/select.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# select

The `select` expression chooses from a set of blocking operations and proceeds with the branch that becomes available first.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Available first is not 100% accurate in MT or even if both are already available. I'm not sure how to frame the difference.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If any actions are directly executable, select_impl immediately returns the result of the first action with delivery state delivered or closed. So IIUC "available first" should be good for that scenario.

With multithreading everything is a bit more complicated, of course. But even there the action that first manages to activate the select context is chosen.

Maybe we just need a different word for "available"?

Suggested change
The `select` expression chooses from a set of blocking operations and proceeds with the branch that becomes available first.
The `select` expression chooses from a set of blocking operations and proceeds with the branch that activates first.


## Syntax

The expression starts with the keyword `select`, followed by a list of one or more `when` branches.
Each branch has a condition and a body, separated by either
a statement separator or the keyword `then`.
Optionally, the last branch may be `else` (without condition). This denotes the `select` action as non-blocking.
The expression closes with an `end` keyword.

> NOTE:
> `select` is similar to a [`case` expression](./case.md) with all branches referring to potentially blocking operations.

Each condition is either a call to a select action or an assignment whose right-hand side is a call to a select action.

```crystal
select
straight-shoota marked this conversation as resolved.
Show resolved Hide resolved
when foo = foo_channel.receive
puts foo
when bar = bar_channel.receive?
puts bar
when baz_channel.send
exit
when timeout(5.seconds)
puts "Timeout"
end
```

## Select actions

A select action call calls a method with the implicit suffix `_select_action`,
or `_select_action?` for a call with `?` suffix.
This method returns an instance of the select action.

The `select` expression initiates the select action associated with each branch. If either of them immediately returns, it proceeds with that.
Otherwise it waits for completion. As soon as one branch completes, all
others are canceled.
An `else` branch completes immediately so there will not be any waiting.

Execution continues in the completed branch.
If the branch condition is an assignment, the result of the select call is assigned to the target variable.

<!-- markdownlint-disable MD046 -->

!!! info "Select actions in the standard library"
The standard library provides the following select actions:

* `Channel#send_select_action`
* `Channel#receive_select_action`
* `Channel#receive_select_action?`
* [`::timeout_select_action`](https://crystal-lang.org/api/toplevel.html#timeout_select_action(timeout:Time::Span):Channel::TimeoutAction-class-method)
Loading