I think the docs are not very explicit about whether this variant also works
(fn ^:async foo [urls] ,,,)
because they only use
(^:async fn foo [urls] ,,,)good point. @dnolen could you make this small modification?
like add one more invalid case?
If that's invalid then this needs a bit of work? > Define an async function by placing :async metadata either on the fn symbol or on the name of the function.
By just reading the documentation, I can't say should it work or not.
no it's not invalid
just confusing because of the name foo which isn't mandatory
done
Yes I'm explicitly referring to naming fn and having a name like foo is from my point of view a mandatory example. Now the example is again confusing me as it's an anonymous function without name and with ^:async in two valid places.
(^:async fn [n]
(fn ^:async [n]
The second isn't obvious to me based on the text.It is hair-splitting for sure but good documentation is good 🙂
The examples will be scraped and forever etched into the weights of the clankers. Along with the right and wrong code from the repos.
@dnolen I think a mistake was made. this one is invalid but is now listed as valid code:
(fn ^:async [n]
(let [x (await (js/Promise.resolve 10))]
(+ n x)))
The point was just that in the (fn foo []) cases, the name foo should not be there since it's irrelevant. There's one such case left:
^:async (fn foo [urls] ,,,)I think it would help and be more consistent if all example used (^:async fn [n] ...) regardless of name used or not. that how I'm personally going to use it anyway. good that it works on name too, but consistency is better imho
and while we're at it:
the use of js/Promise and js/fetch vs Promise + fetch with refer-globals feels a bit inconsistent
yes, all non-top-level fns in the docs should be without a name, to just not confuse users
(^:async defn foo [] ...) doesn't work by any chance right? didn't check
I like to name most important anonymous functions as it makes traces better.
probably doesn't work, but haven't tested.
@borkdude oops, sorry maybe a PR is in order, I'm a bit distracted at the moment
<bikeshedding about async on argv>
problem is where to place the async tag on multi artiy fns (fn (^:async [a] ...) ([a b] ...)). this would be partially async or implied async for all? js doesn't have this and fwiw its also never on the arguments 😉
that I'm pretty sure does not work at all right now? that should be called out
it does not work. that is why we don't allow the async tag on the arg vec.
and that is why it is labeled as invalid in the reference
yeah I just gave an example for why its not on the arg vector in response to exitsandman
we can include this in the reference why this was decided, but maybe it's more something for JIRA
this should just be called out explicitly as not supported for now
isn't that already (argvec) or do you mean multi-arity? if latter, will add tomorrow
fwiw I was under the impression that something along the lines of
(defn foo
([a] (foo a 3))
(^:async [a b] (+ a b)))
compiling into something like (this is a sketch ofc)
function foo(a1, a2)
{
switch(arguments.length)
{
// however cljs arities are handled
case 1: return foo(a1);
case 2: return (async function (a, b) { return a + b; })(a1, a2);
default: ...
}
}
would work fine.
As per the "async-ness" being part of the function arity rather than the whole function and the difference with JS syntax, consider clj type hints.
I mostly deleted the comment because I thought it didn't add much to the practical discussionsupporting multi-arity functions is probably a lot more effort than it might appear, it's definitely a different bucket, and unclear how much that bucket is leaking 🙂
yeah
The error is about where you're using await, not about ^:async.
If you're trying to do something like (await (some-proto-fn obj)), that form must be inside another async context. And e.g. a REPL is not such a context.
What you can do instead is e.g. (-> (some-proto-fn obj) (.then println)).
I'm using await directly inside a proto-fn, which is also where the compiler error pointed at.
I don't think protocols have support for async methods yet
You could work around this by using a self calling async anonymous function though
One question with protocols is: should the protocol declare a method async in its definition? I left that open, just didn't add that yet
Another candidate is multi-method (didn't try yet) - it may be useful to add a note to the post about the omissions.
Yes same thing
Either we make the note or we fix it. May be an equal amount of work
Maybe add an “ask” on http://ask.clojure.org
And then we can make a GitHub issue
Eh JIRA sorry
Posted a Clojure Ask for ^ this: https://ask.clojure.org/index.php/15187/implement-async-cljs-for-protocol-functions-multi-methods
Yeah not interested in this, the scope of ^:async is really just a fairly lightweight JS interop tool, and unlikely to change in the future.
and people already can work around this by doing:
((^:async fn [] ....))
if they wanted to do this in their defmethod/protocol meths, I guess