Racket -> HTML+JavaScript using Urlang and Ractive

328 views
Skip to first unread message

Daniel Prager

unread,
Mar 16, 2016, 8:57:30 AM3/16/16
to Racket Users
Awesomely, Jens has been working on Urlang: a Racket-ish syntax for JavaScript, using the nanopass compiler infrastructure:

https://github.com/soegaard/urlang

and more ambitiously, a Racket (subset) ->JavaScript compiler (rjs), taking a distinct approach from Whalesong.

* * *

Just using plain Urlang together with sxml, Bootstrap (for css), and notably Ractive.js for templating and data-binding I made the following demo / proof-of-concept:

Note: no heavyweight js runtime required: actually no runtime at all.




The abstractions are a bit leaky, but I'm quietly excited about where this sort of approach could lead.

What do you think?

Dan


John Clements

unread,
Mar 16, 2016, 12:03:34 PM3/16/16
to Daniel Prager, Racket Users

> On Mar 16, 2016, at 5:56 AM, Daniel Prager <daniel....@gmail.com> wrote:
>
> Awesomely, Jens has been working on Urlang: a Racket-ish syntax for JavaScript, using the nanopass compiler infrastructure:
>
> https://github.com/soegaard/urlang

Looks very cool. I’ll use this the next time I write JS code.

Thanks!

John

>
> and more ambitiously, a Racket (subset) ->JavaScript compiler (rjs), taking a distinct approach from Whalesong.
>
> * * *
>
> Just using plain Urlang together with sxml, Bootstrap (for css), and notably Ractive.js for templating and data-binding I made the following demo / proof-of-concept:
>
> http://htmlpreview.github.io/?https://github.com/danprager/urlang/blob/master/urlang-examples/ractive/ractive-bootstrap-example.html
>
> Note: no heavyweight js runtime required: actually no runtime at all.
>
>
> Racket source: https://github.com/danprager/urlang/blob/master/urlang-examples/ractive/ractive-bootstrap-example.rkt
>
> HTML output (including embedded JavaScript): https://github.com/danprager/urlang/blob/master/urlang-examples/ractive/ractive-bootstrap-example.html
>
> The abstractions are a bit leaky, but I'm quietly excited about where this sort of approach could lead.
>
> What do you think?
>
> Dan
>
>
>
> --
> You received this message because you are subscribed to the Google Groups "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



Greg Trzeciak

unread,
Mar 16, 2016, 5:18:42 PM3/16/16
to Racket Users
Thanks Dan, seems to be exactly what I need (especially the combination with ractive.js! BTW you couldn't find js framework with name more fitting to work with racket ;)
I am only curious what racket subset does urlang include or rather what won't work in urlang.

Jens Axel Søgaard

unread,
Mar 16, 2016, 5:32:22 PM3/16/16
to Greg Trzeciak, Racket Users
2016-03-16 22:18 GMT+01:00 Greg Trzeciak <gtrz...@gmail.com>:

Thanks Dan, seems to be exactly what I need (especially the combination with ractive.js! BTW you couldn't find js framework with name more fitting to work with racket ;)
I am only curious what racket subset does urlang include or rather what won't work in urlang.

Hi Greg,

Think of Urlang as JavaScript with s-expression syntax.
The core urlang language includes constructs that mirror JavaScript almost one-to-one.
So Urlang is not "Racket to JavaScript compiler".

There are few miniscule differences:
    -   functions support optional arguments
    -  The = operator generates === in JavaScript
    -  if will only count the false  value as false (zero is not considered to be true)
   
That said: Urlang does support macros, which means you can write
constructs that expand into core Urlang.

In urlang/for you will find a Racket-ish for constructs.
That is  for, for*, for/sum, for*/sum etc 


In urlang/extra you will find some often used macros:

These constructs can be used as expressions:

;     (begin0 expr statement ...)
;     (when   test statement ... expr)
;     (unless test statement ... expr)

;     (cond [test statement ... expr] ...)
;     (case val-expr clause ...)
;          where clause is  [(datum ...) statement ... expr]
;                       or  [else        statement ... expr]
;     (letrec ([id val-expr] ...) statement ... expr)
;     (let*   ([id val-expr] ...) statement ... expr)

;; These constructs can be used as statements:
;     (swhen   test statement ...)
;     (sunless test statement ...)
;     (scond  [test statement ...] ...)


We are working on making some more examples.

/Jens Axel





 

Greg Trzeciak

unread,
Mar 16, 2016, 5:50:05 PM3/16/16
to Racket Users, gtrz...@gmail.com, jens...@soegaard.net
On Wednesday, March 16, 2016 at 10:32:22 PM UTC+1, Jens Axel Søgaard wrote:
> 2016-03-16 22:18 GMT+01:00 Greg Trzeciak <gtrz...@gmail.com>:
>
>
> Thanks Dan, seems to be exactly what I need (especially the combination with ractive.js! BTW you couldn't find js framework with name more fitting to work with racket ;)
>
> I am only curious what racket subset does urlang include or rather what won't work in urlang.
>
>
> Hi Greg,
>
>
> Think of Urlang as JavaScript with s-expression syntax.
> The core urlang language includes constructs that mirror JavaScript almost one-to-one.
>
> So Urlang is not "Racket to JavaScript compiler".

Got it. In other words:

"Urlang is a Racket flavoured S-expression syntax for Javascript"

Thank you for your explanation - still seems like a good fit for one of my projects (as I needed something more lightweight than Whalesong) so I will try it out shortly.

Greg


Jens Axel Søgaard

unread,
Mar 16, 2016, 5:54:50 PM3/16/16
to Greg Trzeciak, Racket Users
2016-03-16 22:50 GMT+01:00 Greg Trzeciak <gtrz...@gmail.com>:
"Urlang is a Racket flavoured S-expression syntax for Javascript"

Can I steal that for a tag-line?
 
Thank you for your explanation - still seems like a good fit for one of my projects (as I needed something more lightweight than Whalesong) so I will try it out shortly.

Sounds great. Don't hesitate to send feedback.

/Jens Axel

 

Greg Trzeciak

unread,
Mar 16, 2016, 6:01:06 PM3/16/16
to Racket Users, gtrz...@gmail.com, jens...@soegaard.net
On Wednesday, March 16, 2016 at 10:54:50 PM UTC+1, Jens Axel Søgaard wrote:
> 2016-03-16 22:50 GMT+01:00 Greg Trzeciak <gtrz...@gmail.com>:
> "Urlang is a Racket flavoured S-expression syntax for Javascript"
>
>
>
> Can I steal that for a tag-line?
>  

Feel free!

Armon Toubman

unread,
Mar 18, 2016, 4:29:30 AM3/18/16
to Racket Users
On Wednesday, March 16, 2016 at 1:57:30 PM UTC+1, Daniel Prager wrote:
This looks great. Would it be possible to extend this to React Native [1], so we can write mobile apps in Racket?

[1] https://facebook.github.io/react-native/

Armon

Andrew Gwozdziewycz

unread,
Mar 18, 2016, 9:47:11 AM3/18/16
to Daniel Prager, Racket Users
Very neat! I had to make some changes to it before I could see it. This is mostly around "mixed-content" due to mixing HTTPS with HTTP for assets. Otherwise, all this is *very* promising.



--

Matthew Butterick

unread,
Mar 18, 2016, 1:38:39 PM3/18/16
to Daniel Prager, Racket Users
> and more ambitiously, a Racket (subset) ->JavaScript compiler (rjs), taking a distinct approach from Whalesong.


The short answer: +1

The longer: I am no fan of JavaScript, which I consider a brain-eating virus. [1] But IMO the "frameworkification" of JS has made it even worse. Yes, the wheel-reinvention critique is also leveled at Lisps. But never have so many devoted so much effort to creating ever-larger elephants to crush ever-smaller peanuts. [2]

And yes, I maintain a package called `sugar`. Dry humor intended. Would that JS frameworks acknowledged their place in the world. Which is mostly to create mutually unintelligible dialects of JS.

Today, I use Pollen as a JS preprocessor. [3] That's a lot better than JS alone. But I notice that 90% of my JS code uses 10% of the language. The usual: variables, loops, functions. Manipulation of the DOM. Async requests. The idea of a subset of Racket that compiles to this kind of statistically probable subset of JS is very appealing. Especially if it can obviate the need or should I say "need" for a JS framework.


[1] https://youtu.be/20GGVNBykaw?t=128
[2] http://stackoverflow.com/questions/3811678/add-two-variables-using-jquery
[3] http://pollenpub.com

Daniel Prager

unread,
Mar 18, 2016, 4:28:27 PM3/18/16
to Matthew Butterick, Racket Users
Matthew writes:
> The idea of a subset of Racket that compiles to this kind of statistically probable subset of JS is very appealing.

Agreed. The way Jens has split it up is that Urlang is a thin, cleaned-up Racket-ish syntax for ES5, with a bit of sugar and a macro capability.

Then there's rjs, which includes a runtime, and aims to compile a substantive subset of Racket. Of course there's going to be a trade-off between completeness and runtime-size, etc.


> Especially if it can obviate the need or should I say "need" for a JS framework.

So, I'm currently looking at some of the "better" JS / HTML / CSS frameworks / libraries with a view to being able to hide the detail and relatively easily spin-up browser-hosted applications. E.g.
  • CSS / reponsiveness: e.g. Bootstrap
  • DOM manipulation & binding: e.g Ractive, Mithril
  • Data structures: e.g. mori
  • Graphics: e.g. D3
I take it obviating the need for frameworks would essentially mean pulling necessary functionality up into Racket: analogous to writing in Racket rather than using interop to access external e.g. C/C++ libraries from regular Racket.

Is that what you mean? Sounds good to me, but more of a "longer term" project. Elm might be a good model for this.

Dan

Matthew Butterick

unread,
Mar 19, 2016, 6:44:52 PM3/19/16
to Daniel Prager, Racket Users
When you put it that way, subjectively it still sounds good. I'd use it. But objectively I can't foresee that it would be a wise investment of anyone's Racket time. Let's face it: any web framework is lucky to live 5 yrs before developers tire of it and move onto the next thing, or browser changes make it obsolete. I have a shoddy `css-tools` library that I sometimes think about cleaning up for public consumption, and then I get dizzy and move on to something else. 

Daniel Prager

unread,
Mar 23, 2016, 7:42:41 AM3/23/16
to Racket Users
On Sun, Mar 20, 2016 at 9:44 AM, Matthew Butterick <m...@mbtype.com> wrote:
When you put it that way, subjectively it still sounds good. I'd use it. But objectively I can't foresee that it would be a wise investment of anyone's Racket time. Let's face it: any web framework is lucky to live 5 yrs before developers tire of it and move onto the next thing, or browser changes make it obsolete.

The shifting of the underlying platform is inevitable -- perhaps eventually it will settle down -- and empirically your point about web-frameworks checks out, suggesting that it would be unwise to bake in reliance on any particular framework.

That said, I reckon that there are gains to be made via making use of existing JavaScript frameworks and libraries.

OTOH: Here's a new example from Jens that has zero dependencies on external JS - a simple Space Invaders game in Urlang: http://soegaard.github.io/urlang/space-invaders.html

Dan

Jens Axel Søgaard

unread,
Mar 23, 2016, 11:21:59 AM3/23/16
to Daniel Prager, Racket Users
The goal for the core Urlang language is to be almost 1-to-1 with JavaScript.
Therefore I haven't used any JavaScript libraries. As Dan's examples
shows (see urlang/urlang-examples) it is straightforward to use existing
JavaScript libraries.

There are a few predefined macros that one can optionally use:
cond, case, for etc which are Urlang macros that expand into
core Urlang (think JavaScript) constructs. The ability to extend JavaScript
with a sane macro system was what I wanted to achieve.

The source code for Space Invaders is a port of an HtDP-style program.
The attempt was to match the original HtDP-style and I think it turned out pretty well.

It contains an ad-hoc implementation of structs in Urlang (JavaScript), so when
you want to access the x-coordinate of a player p, you will see (player-x p)
in the code. If the program was written from scratch I would have used p.x
which is the standard JavaScript notation of access x in an object (or array) p.

If anyone wonders why I chose (var [x 42] [y 43]) rather than adding
an internal define to Urlang - it is due to the scoping rules. The
var-form follows the scoping rules of JavaScript - which means it
has block-scope.

If normal local scope is needed one can use the the let-macro (or letrec*)
from urlang/extra.

/Jens Axel




--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
--
Jens Axel Søgaard

Reply all
Reply to author
Forward
0 new messages