-
-
Notifications
You must be signed in to change notification settings - Fork 250
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
Add documentation for select
#747
Conversation
✅ Deploy Preview for crystal-book ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure we should document the internal implementation details until we move on to a public API? For the time being I'd document sugar syntax (the supported expressions) and forego the details of the syntax expansion (internal detail).
BTW: I'm surprised that #timeout_select_action
is documented, it even returns a Channel::TimeoutAction
that isn't documented.
Also: we can select on Channel#send(M)
.
Well this documents the current state. If we change the API, we'll have to change the documentation. But at least we'll have something to start with. AFAIK the |
Not sure what you mean by that... Could you clarify? |
I agree the syntax expansion shouldn't change, but we never know and we can't use the knowledge anyway (because private classes) 🤷 I mean that we can select on send too, but I see you did list select
when channel.send(message)
when timeout(5.seconds)
end |
Yeah, we'll need a guide on how to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I always come back to https://gist.github.com/bcardiff/289953a80eb3a0512a2a2f8c8dfeb1db to see the potential uses of select and it's variation.
That guide might serve better for a guide that covers the use cases rather than the language semantics.
Maybe for the language semantics, if we want to be precise we should mention the conversion of select statements to Channel.select
/Channel.non_blocking_select
and refer to that (future) guide for further uses.
The proposed document is short and concise, so if we iterate on the comments I think is a good addition. Definitely the usage guide will be well received.
@@ -0,0 +1,52 @@ | |||
# select | |||
|
|||
The `select` expression chooses from a set of blocking operations and proceeds with the branch that becomes available first. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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"?
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. |
docs/syntax_and_semantics/select.md
Outdated
|
||
## Select actions | ||
|
||
A select action call calls a method with the implicit suffix "_select_action". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ?
suffix means the transformation is foo?
-> foo_select_action?
, and foo
-> foo_select_action
🕵️ .
I don't remember if foo
and foo_select_action
are constrained to have some relation in their type signature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a mention of the suffix.
I don't remember if
foo
andfoo_select_action
are constrained to have some relation in their type signature.
I don't think so. There's no need for any constraints because all calls in a select
expression's where
condition are expanded. If a method signature doesn't match, the type checker will complain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They do.
def foo_select_action : Channel::TimeoutAction
timeout_select_action(1.second)
end
a =
select
when x = foo
x
else
nil
end
complains with
In foo.ign.cr:15:12
15 | when x = foo
^--
Error: undefined local variable or method 'foo' for top-level
If we define foo
with the wrong type
def foo : Int32
0
end
we get
14 | select
^
Error: can't cast (Channel::NotReady | Nil) to Int32
Since Channel::TimeoutAction
includes SelectAction(Nil)
we need def foo : Nil
for things to compile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, interesting. I have no idea where in the compiler that would be happening, though 😆
Literal expander just transforms the calls without any checking.
No description provided.