What will Rebol on the Web Look Like?

I wanted to say that the #2 and #3 merge did indeed go very well, and we no longer have to think of these as separate scenarios.

To recap what that meant: #2 was the idea that people would be able to code applications from a "Rebol Worldview" in the browser. They can use no JavaScript at all if they like (or throw in little bits of "inline JavaScript" when it suits them...e.g. they find there isn't something already bridged in the Rebol routines to do what they want.)

Because we have the baseline of that working, you can write a traditional app with PRINT and ASK TEXT! (formerly INPUT)...also doing READs from URL!s off their own domain (wherever the app is hosted) or from remote domains (if the files support CORS).

That isn't just enough to write a console with, that's enough to run the actual common console extension used by the interpreter itself. Also, @BrianOtto made a game/tutorial demo, and I made a guided interactivity test.

The big question is now about how people will make such apps that make the ReplPad console disappear into the background. I kind of want to punt on that until we know more...so if people could tolerate the idea that their applications are launched from the console I'd like to go that route. We can find various ways of making the URL format that auto-launches your app more palatable.

So what about option 1?

Option 1 was the idea that someone's web page is mostly JavaScript, and Rebol sneaks in as an assistant...to do parsing, or other various things.

This isn't impossible, but it's very hard to guarantee that a Rebol script doesn't have any I/O. And if it does have I/O...and there's no ReplPad...what should it do? Write to the JavaScript console? Should any ASK for input be treated as an error?

Imagine you want to do something like:

 var url = "http://hostilefork.com"  ; pretend I enabled CORS :-/
 var title = reb.Spell(
      "parse as text! read", url, 
          "[thru <title> copy title to </title>]",
      "title"
 );

That seems pretty cool. The variadic API even saves you from having to concatenate strings with +, which would make you put awkward spacing in that could be easy to forget ("... read " + url + " [thru..."). It's more readable this way.

But the problem I mentioned is still there: JavaScript cannot synchronously handle a network request like this. It just can't. You have to write something more like:

 var url = "http://hostilefork.com"
 reb.Promise(
      "parse as text! read", url, 
          "[thru <title> copy title to </title>]",
      "title"
 ).then(function(title) {
     ... do stuff with title ...
 );

Or, if you've followed all the rules of your entire stack to the top of your JavaScript code with async functions, you can say:

 var url = "http://hostilefork.com"
 var title = reb.Spell(await reb.Promise(
      "parse as text! read", url, 
          "[thru <title> copy title to </title>]",
      "title"
 ));

We can probably make this slightly better as title = await reb.SpellPromise(...) (or PromiseSpell? SpellAsync?)

But less important than the naming convention is the fundamental question: how did the caller know whether or not the Rebol code they called was going to be able to complete without doing something that requires yield processing in the JavaScript callsite?

This is one splendid argument for why Option #2 is a way forward for authoring code on the web. Because when you're not putting arbitrary JavaScript code in the driver's seat, you just don't worry about it. The entire application runs inside of One Giant reb.Promise().

But Would JS Programmers See Value in #1?

I think it's kind of odious to imagine every single thing you'd want to do with Rebol to require asynchronous handling. But the design of the API is pretty clever IMO, and it means you don't necessarily have to do a bunch of nitpicky API calls to get the data you want...you can usually tie it all up with one single call where the Rebol code has pared out everything you need...and you get the JS result you want. If we could transform BLOCK!s of data items to a JavaScript array (reb.UnboxArrayPromise()) then this could be even more true.

I also pointed out in the post "On Giving libRebol.JS More Powers Than JavaScript", I don't think JS programmers will see this as any particularly bad thing. They just plug along.

So if every single entry point to calling the Rebol interpreter was a promise, they'd probably like it. More time to let the main loop run! In fact, they're getting a powerful WASM web worker experience for free...it's like they can do background processing and still paint and process input. Hence I may be overthinking this, and we should just tell people using #1 to always use the Promise APIs because the non-Promise ones might error if any asynchronous requirement creeps in.

FWIW: This Is Pretty Well Understood Now, and Going Great...we just need to have people understand why it's great.

2 Likes