-
Notifications
You must be signed in to change notification settings - Fork 22
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 if! (if-bang) keyword to computation expressions #863
Comments
This seems reasonable |
Should that include let x = async {
if! asyncBool then
do! task1
elif! anotherAsyncBool then
do! task2
else
do! task3
} |
@nikonthethird probably yes, and pretty effortless, since |
Good catch, that's really quite reasonable! :3 |
It would be good to consider other typical branching constructs as well; in particular the "while" keyword. A good use case would be using ADO.NET; not sure if this is already supported. Normally you would need a recursive function to do this - would be much easier with .
|
@mvkara There's a major difference between
So I think it's a good idea but probably belongs in a separate suggestion. |
I agree with @Tarmil -- plus that it's likely these constructs should be designed to incorporate with |
Wanted to add one more comment for discussion, not directly related to the topic, but not sure where to put it - it would be nice to support bang operations inside if without overhead of raising 0 to async:
this can be easily done in C#, but not F#:
|
It is actually possible to implement a type AsyncBuilder with
member this.While (guard, body) =
let guard = guard ()
let rec loop = function
| false -> this.Zero ()
| _ -> this.Combine (body, this.Bind (guard, loop))
this.Bind (guard, loop)
Async.RunSynchronously (async {
let mutable count = 5
while async { return count > 0 } do
do printfn "Counting down: %d" count
do count <- count - 1
}) |
@Lanayx The problem in your code isn't the // This does NOT work, even without an if, because there's a let! inside a let:
async {
let sum =
let! x = someAsyncCode()
x + y
return sum * 2
}
// This DOES work, even with the if:
async {
if someCondition() then
let! x = someAsyncCode()
return x + y
else
return y * 2
} |
@Tarmil Thanks for the explanation! However as you can see, the problem is not in my code, but in this nested limitation - C# doesn't have such limitation and it would be nice not to have it in F# either. |
@Lanayx I think I understand the problem. But having different types on if-else branches feel wrong to me. |
@yatli this is very helpful for caching scenarios - if local cache exists return cached value, otherwise make async call. To go over this limitation I had to use mutable variable |
Hmm. Something like a new function But I still think it's better to use the It's just like you cannot write |
@yatli yes, if this cast is free :) With return it is an additional allocation and method call, and when it's on the hot path (like in my case), this should be avoided. |
could this be done, in a short-circuiting way? let x = async {
if! asyncBool and asyncBool2 then
do! task1
elif! anotherAsyncBool or asyncBool3 then
do! task2
else
do! task3
} |
@Lanayx I don't think it's optimized that way... More like a syntax sugar that wraps 0 into the completed task. #LINQPad optimize+
async void Main()
{
await compute(3);
}
async System.Threading.Tasks.Task<int> realAsync() {
await System.Threading.Tasks.Task.Delay(100);
return 0;
}
async System.Threading.Tasks.Task<int> compute(int x) => x > 2 ? await realAsync() : 0; Turns to:
You see, IL_0076 is the last one from the realAsync branch -- before that, the result is unwrapped from |
Thank you @Lanayx , I didn't know it could pull that off. Would you mind opening another thread to continue the discussion? There are both syntax and compiler optimization issues, but out of scope of this suggestion. |
Consider allowing an elaboration to a new If F# automatically desugars it to Perhaps a related suggestion then is to automatically desugar "lower power" computation expression operations in terms of explicitly defined "higher power" operations if the lower power operations are not available. E.g if |
Add if! (if-bang) keyword to computation expressions
I propose we extend computation expressions with a new keyword,
if!
(if-bang), that functions alet!
(let-bang) combined with an if statement. For example, instead of writing:or even:
We should be able to do:
Pros and Cons
Pros: Aids code readability in specialized cases.
Cons: It's work, and it increases complexity. (whether or not this is worth the effort for potentially such small return is up to debate / whoever would do it, but I figure it's worth filing [probably low priority :) ] since I am not aware of a prior suggestion -- would be brownie points for the F# language)
Extra information
S
Related suggestions: (put links to related suggestions here)
#572
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
The text was updated successfully, but these errors were encountered: