Thank you for your thoughtful answer, it's clarified some issues. I'm afraid it also raises more questions for me (I probably need to go study CoffeeScript some more). BTW, the text I added is actually from the first example - the simplest:
await $.getJSON url, defer json
Is the following right? Syntactically, "defer json" is an argument to the function "$.getJSON". So you could write it like this:
await $.getJSON( url, defer(json) )
The code we are waiting for is the "$.getJSON" call. That code indicates that it is finished by calling the function returned by defer.
But what does the function returned by defer do? It looks like it (somehow) sets its argument to the result... so in the above example, "json" (somehow) gets the result of the call; in your example, "x" (somehow) gets a value. I'm guessing it's some convenient compiler magic that ICS does, and not an issue of CoffeeScript syntax.
An upshot of this is you can't give defer any old argument (e.g. a numerical value) - it has to be a variable that is capable of being set.
Also, who is the "callee"? A "callee" is a function that is called... Oh, does it mean (eg) "$.getJSON" is a callee, and it calls the callback function given to it (in the jQuery docs, it's notated as "success(data, textStatus, jqXHR)"; here, that success function is the function returned by defer). I guess, given the purpose of ICS, there will always be a callee in the block - but it seems to me that, syntactically, you could just directly call the function returned by defer. Ah... but (I bet) part of the compiler magic is that you are only allowed to call the function returned by defer from within another function - this is because the result of that other function is needed in order to set the argument of defer to it. Whew.
One last thing: the description talks about "deferrals" begin "fulfilled", but it doesn't say where these defarrals come from. Now, I think they are created by calling defer.
Hmmm.... it's probably better for me to think about this in terms of lisp macros, instead of C calls, as macros allow you to do weird source code transformations, like setting the value of a variable given as an "argument". i.e. ICS is a macro.
Note that I haven't tested ICS so it's only based on my understanding of the examples/docs.
"Is the following right? Syntactically, "defer json" is an argument to the function "$.getJSON". So you could write it like this:
await $.getJSON( url, defer(json) )"
Yes, exactly.
"'m guessing it's some convenient compiler magic that ICS does"
Yes, exactly. When you say "defer(x)", it basically returns a callback like this:
function(result) {
*x = result;
Code to terminate the await block*
}
"One last thing: the description talks about "deferrals" begin "fulfilled", but it doesn't say how they are created. Now, I think they are created by calling defer."
Yeah, defer returns a callback and when you call it, it "fulfills" the await, i.e. you tell await that you're done with that async block.
Thanks a second time, I'm getting there! I realized one can look at the transformed javascript output, to see just what it does. The setting of the variable in the defer becomes:
Presumably, when
the function that __iced_deferrals.defer returns is
called by the code in .getJSON that delivers the result, it will set arguments[0] to that result, and then call the assign_fn above. This will set json to that result.
Also, I realize that it doesn't set json to the returned value of $.getJSON, as $.getJSON doesn't return anything - it uses a callback to deliver its result. It seems that ICS always works this way - which I guess implies that the use-case it's for always uses callbacks...
BTW: I'm not sure why the above has a function which is then called immediately. Maybe a coffeescript thing, for separating namespaces? I assume the lineno: 6 is for debugging - I recall some debate against this. Good to see it got in.
About the function which is called automatically, it's a common pattern in javascript. It's used to create a new namespace/modules as block are defined per function instead of {}.
And, you are right that we're not assigning the return value of $.getJSON. Basically, once $.getJSON has finished with the request, it will call a function with the result. This result is set to the variable passed to defer. It's a bit of a brain teaser but that's the whole point of the await/defer thingy. Instead of using a callback to retrieve the result as an argument, you just write a variable after defer and you receive it.
defer is a function which returns another function. When that returned function is called, we get out of the await block.
So, to take the same example:
Here, defer(out[i]) returns a function. We pass this function to search.Search is like this:
And here, by calling callback, which is the function returned by defer, it will end the await block.Here's a trivial example:
defer(x) returns a callback, it's given to some_function. And some_function calls it, which ends the await block.