racketscript / racketscript

Racket to JavaScript Compiler
MIT License
713 stars 32 forks source link

Add support for `async` / `await` #84

Open amirouche opened 7 years ago

amirouche commented 7 years ago

In modern javascript, there is async and await new keywords that allows to write asynchronous code that looks like synchronous code. For instance,

async function fetchPosts() {
    let response = await fetch('/api/posts');
    if (response.status === 200) {
         let posts = await response.json();
         return posts;
    }
}

Is it possible to have support for that? I don't how to port my framework to racketscript without this (see. #61).

The above should be possible to be written in racketscript using a syntax that looks like the following:

(define-async (fetch-posts
 (let ((response (await (fetch "/api/posts"))))
       (if (= (response-status response) 200)
           (await (response-json response)))))

It should also be possible to define async lambda.

vishesh commented 7 years ago

Sure I can do that. Is it ok if I do in weekend, or you are totally blocked?

amirouche commented 7 years ago

It's ok I can wait.

jackfirth commented 7 years ago

Could this be an ordinary Racket macro? As far as I know, it's a syntactic feature of JS only; there's no special runtime support for it.

vishesh commented 7 years ago

@jackfirth Yes. That's what I originally intended. Otherwise just adding this to AST is probably a 10 min patch.

gregid commented 7 years ago

+1 for this feature to be implemented

vishesh commented 7 years ago

@amirouche Just wanted to do a quick update on this. I'm still working on this, but this will take some time before I get first prototype up. There is slight awkwardness with yield with recursive functions, and since Racket uses recursion for loops, the semantics needs to be right (preferably like Racket).

amirouche commented 7 years ago

FWIW, I am not interested in yield. The only thing I need is the ability to declare a lambda async and call another lambda with await.

Hope that helps.

amirouche commented 7 years ago

In BiwaScheme, I use a biwascheme primitive that rely on call/cc. In Javascript, I use async/await. FWIW here is the code that converts the async function into regular callback style function.

amirouche commented 7 years ago

In BiwaScheme, I use a biwascheme primitive that rely on call/cc. In Javascript, I use async/await. FWIW here is the code that converts the async function into regular callback style function. The async function when called without await returns a promise.

gregid commented 6 years ago

Is there any chance to implement this any time soon?

vishesh commented 6 years ago

@gregid I doubt I will be able to pushthis in next couple of months. I was exploring using ES6 style async await vs macros, but got interrupted with other stuff.

stchang commented 3 years ago

@vishesh As a first step, could we just add async and await cases to %js-ffi?

vishesh commented 3 years ago

Yes, I think that should be fairly easy to do.

stchang commented 3 years ago

Sounds good. I'll spin out a separate task for it, in case someone is interested in working on it.

stchang commented 3 years ago

I'd like to continue discussion because to me, it's not clear what the right thing to do here is. Philosophically, this issue seems different because it moves past the original "compile Racket to js" motivation, and into the "lift js features into new RacketScript abstractions" territory, which is a bigger (but interesting) space to explore.

Does anyone know what other js compilers have done for these kinds of language design issues, eg does Clojurescript or Rescript offer anything beyond raw js interop for async?

From the Racket side, would it be useful to compile existing Racket features (futures or promises?) to async?

gamburgm commented 3 years ago

IIUC, Clojurescript doesn't have any direct support for async/await, but there are some libraries that expose it in different ways.

amirouche commented 3 years ago

async / await keywords are a language design mistake. It is better to have async without keywords.

arthertz commented 2 years ago

I think it would be cool to include some support for promises and futures. As far as I can tell, javascript's await is very close to the touch procedure in racket/futures. I believe that async is closer to Racket futures than promise. The promise feature is more like a call-by-need evaluation, while future will evaluate the expression asynchronously or until forced, just like async.

yfzhe commented 1 year ago

The promise feature is more like a call-by-need evaluation

No, promises are strict-evaluated. It does its computation and then trigger "callback" base on the eventual state (fullfiled or rejected).

I think before adding async/await to RacketScript, we can bring promise into RacketScript first.