As this question is huge, I will give my view on this question so that you can simply tell me whether I am right or not. If not, where to correct. If my view is superficial, please present an overview of F# async usage. In mu understanding, to write async program, you need to put async code into "async" block like async{expression}, and use "let!" or "use!" to bind names to primitives, then you need to use method to run this async expression like "Async.Run". In addition, you can use exception handling to deal with exception, and cancellation to cancel when necessary. I also know there are several primitives that defined in F# core libraries, and F# extension of I/O operation. I just need to make sure the relation between these things. If you think my view on async workflows is superficial, please give an overview usage like what I have mentioned above. Thank you very much!
This question is huge, so at best, I can highlight some ideas and point you to learning resources and examples.
The description in the question isn't wrong (though there is no Async.Run function). But the main point about Asyncs is how they execute and why the way they execute is useful.
An async block defines a piece of code that becomes an Async<'T> object, which can be seen as a computation that can be executed at a later time. The Async returns an object of type 'T when its execution has completed -- if it has neither failed nor been cancelled.
let!, do! and use! are used inside of an async block to run another Async and, in the cases of let! and use!, bind its result to a name inside the current async. Unlike for example normal let, which simply binds any value to a name, the versions with an exclamation mark explicitly "import" the result of another async.
When an Async depends on another and waits for its result, such as with a let! binding, it normally does not block a thread. Asyncs utilize the .NET thread pool for easy parallel execution, and after an Async completes that another Async depends on, a continuation runs the remainder of the dependent Async.
The Async functions offer many ready-made ways to run Asyncs, such as Async.Start, which is a simple dispatch of an Async with no result, Async.RunSynchronously, which runs the Async and returns its result as if it were a normal function, Async.Parallel, which combines a sequence of Asyncs into one that executes them in parallel, or Async.StartAsTask, which runs an Async as an independent task. Further methods allow composition of Asyncs in terms of cancellation, or explicit control over continuation after an exception or cancellation.
Asyncs are very useful where waiting times are included: otherwise blocking calls can use Asyncs to not block execution, for example in I/O bound functions.
The best introductions to F# Asyncs I know are written, or co-written, by Don Syme, the lead designer of F#:
The chapter Reactive, Asynchronous, and Parallel Programming in the book Expert F#
A blog post with examples for asyncronous agents
The blog post introducing Asyncs in late 2007
Related
I have read this article:
https://www.compositional-it.com/news-blog/task-vs-async/ that covers the updates in F# 6.
There is a chapter about the introduction of the task expression and its similarity and differences with async.
My understanding is that the task is a block in which we can do async calls, but it is executed in the regular flow, whereas the async block is the one we know, that creates expressions that will be executed later, on demand.
I use async quite extensively since I'm working with an app doing a lot of data streaming and database writing, so everything is pretty much async.
The only use I can see with the task expression is to interface with async api where I want the async block to run right now.
Essentially, replacing:
async {
do! callMyAsyncOnlyApi ()
} |> Async.RunSynchronously
with
task {
do! callMyAsyncOnlyApi ()
}
which would run instantl and release the cpu while waiting.
I must be missing something :D
The article provides an excellent summary in the conclusion section:
Personally, I reach for async {} by default unless I am dealing with external Task based libraries or I face a specific performance issue (which hasn't happened yet!). I find it fits the functional mindset better and is easier to use.
The reality is however that a great deal of libraries have been written with Task in mind, and it is fantastic that F# now has first class, out of the box support for the pattern.
I do not think there is much to add:
F# always had async and async is a reasonable default
There are a number of advantages of async - it supports cancellation and uses the "generator" model which is more composable (and more F# friendly)
.NET uses Task<T> more prominently, so if you are interfacing with a lot of .NET libraries (as your question suggests), then you may choose task
task can be more efficient if you have CPU-bound and not IO-bound code - so in some cases, you may choose that for performance reasons
We use the term "Async" to allow the code stream to continue without blocking the main stream. This is OK. We want the mainstream to continue without waiting for that process to complete. But usually, "Async and Await" are used together.
My question is; When we add "await", we expect "Async" status in the code stream. In this case, I do not understand what is the benefit of using "Async"? Can someone explain this, thank you, good work.
It's not clear which technology you're referring to. I'll assume you're referring to the async and await keywords that have been added to many languages the last few years.
In that case, this statement is actually incorrect:
We use the term "Async" to allow the code stream to continue without blocking the main stream.
In C#, JavaScript, Python, F#, and Visual Basic, the async keyword does not act asynchronously. It has two effects:
Enable the await keyword within that method/lambda.
Transform that method/lambda into a state machine.
So async does not mean "run this code on a background thread" or anything like that, which is a common but incorrect assumption.
The first point above is important for backwards compatibility. Each of these languages use await as a contextual keyword, so the text "await" in a program is only a keyword if it is in a method marked with async. This allows the languages to introduce the new keywords without breaking any existing code (e.g., someone's code that used await as a variable name).
See this post of mine which collected a lot of the discussion around the keywords as they were originally designed for C#/VB. Those same design decisions carried over almost exactly to other languages as they adopted the keywords, too. One of the resources linked from that post is Eric Lippert's post on why we need an async keyword in addition to an await keyword.
Are coroutines just syntactic sugar around completion blocks and completion blocks will be created under the hood? Or is the concept of coroutines much more complex and broad then just compiler trick aka syntactic sugar
It's not just syntactic sugar, not at all. Coroutines do not block threads, they just suspend execution, thus they encourage non-blocking concurrent programming.
Coroutines do not rely on features of the operating system or the JVM (e.g. they are not mapped to native Threads). Instead, coroutines and suspend functions particularly are transformed by the compiler producing a state machine capable of handling suspensions in general and passing around suspending coroutines keeping their state. This is enabled by Continuations, which are added as a parameter to each and every suspending function by the compiler; this technique is called “Continuation-passing style”.
For details please have a look at https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md
No, coroutines are not syntactic sugar. You can think of coroutines as of functions that can interact with the caller. When you call a normal function, say foo you pass control to foo and have to wait until foo either completes or throws exception. Coroutines are functions which can pass control back to caller, and caller can decide whether coroutine should continue and when and how coroutine should continue. This gives opportunity to implement things which are special language constructs in other languages:
Generators (aka yield keyword) like in C# and JavaScript. Caller continues execution of coroutine when a user wants new value from iterator. Coroutine passes back to caller by calling yield() function, which also passes some value to caller.
Async/await like in C# and JavaScript. Caller continues execution when Future (similar to Task or Promise) gets resolved. Coroutine passes back to caller by calling await() function. Caller passes value to coroutine when Future gets resolved and coroutine observes this value as a result of await() call.
Goroutines/channels in Go.
Unlike C#, JavaScript or Go, Kotlin does not implement any of these features in special syntax. Instead, Kotlin provides only suspend fun syntax, and then you can implement these features yourself (or get existing one from corresponding library called kotlinx.coroutines).
Corutines are syntactic sugar around asyncronous procedures, or, better say, Actors, which are repeatable asynchronous procedures.
Here is an interesting article mentioning implementing async/await in their system: http://joeduffyblog.com/2015/11/19/asynchronous-everything/
Along with this, we added the await and async keywords. A method could be marked async:
async int Foo() { ... }
All this meant was that it was allowed to await inside of it:
async int Bar() {
int x = await Foo();
...
return x * x;
}
Originally this was merely syntactic sugar for all the callback goop above, like it is in C#. Eventually, however, we went way beyond this, in the name of performance, and added lightweight coroutines and linked stacks.
I already know when calling an asynchronous method e.g. myAsync(), the caller e.g. Caller() can continue executing without waiting for it to be finished. But on the other hand, myAsync() also is executing.
public void Caller(){
myAsync();---------------------running
dosometing();------------------running
}
The code next to myAsync() in Caller() will execute with myAsync() at the same time. So could this situation be considered as a kind of concurrency?
update
I prefer use javascript and c#
That very much depends on the concurrency model of your programming language.
If your language allows you to define methods that are "implicitly" running in parallel; then of course, calling myAsync() would use some kind of "concurrency mechanism" (for example a thread) to do whatever that method is supposed to do.
In that sense, the answer to your question is yes. But it might be important to point out that many "common" programming languages (such as Java) would only "work" in such a context when myAsync() would be creating some thread to then run "something" using that thread.
Can synchronous and asynchronous functions be integrated into one call/interface whilst maintaining static typing? If possible, can it remain neutral with inheritance, i.e. not wrapping sync methods in async or vice versa (though this might be the best way).
I've been reading around and see it's generally recommending to keep these separate (http://www.tagwith.com/question_61011_pattern-for-writing-synchronous-and-asynchronous-methods-in-libraries-and-keepin and Maintain both synchronous and asynchronous implementations). However, the reason I want to do this is I'm creating a behaviour tree framework for Dart language and am finding it hard to mix both sync and async 'nodes' together to iterate through. It seems these might need to be kept separate, meaning nodes that would suit a sync approach would have to be async, or the opposite, if they are to be within the same 'tree'.
I'm looking for a solution particularly for Dart lang, although I know this is firmly in the territory of general programming concepts. I'm open to this not being able to be achieved, but worth a shot.
Thank you for reading.
You can of course use sync and async functions together. What you can't do is go back to sync execution after a call of an async function.
Maintaining both sync and async methods is in my opinion mostly a waste of time. Sometimes sync versions are convenient to not to have to invoke an async call for some simple operation but in general Dart async is an integral part of Dart. If you want to use Dart you have to get used to it.
With the new async/await feature you can write code that uses async functions almost the same as when only sync functions are used.