codesections / LearnRakuWith

Learn Raku with interactive coding and a tight feedback loop
Artistic License 2.0
10 stars 2 forks source link

Learn Raku With: HTML Balls

Intro

Raku is, by far, the programming language I'm most excited about. It's powerful, expressive, extensible, and flexible enough to support whatever programming paradigm best suits a task. In fact, I gave a talk last year at FOSDEM about why Raku is the ideal language for writing free software. So it's fair to say that I think as many people as possible should learn the language.

Fortunately, Raku is pretty easy to learn (in the same way as chess or go – easy to learn; difficult to master) and existing Rakoons have written many great resources to help you teach yourself. The main docs do a good job of teaching the language (in addition to their primary role as a reference for more experienced Rakoons). There are also a number of books, including the in-progress Complete Course in Raku (funded via a grant from YAS and thus freely available). Programmers who aren't feeling up to working through a full book could also check out the Raku Guide or could Learn Raku in Y minutes. And if you get stuck on anything, the community is very willing to help out on IRC, Stack Overflow, or the r/rakulang subreddit.

The problem

But, despite all those resources, Raku is slightly harder to get started with than some other languages in one way: There's not a built-in way to get started with beginner code in a way that immediately produces visual results. If you're the sort of person who likes printing output to STDOUT, then it's easy to write your first several Raku scripts. But, if you'd like to display shapes or do other visual tasks, Raku doesn't offer the same out-of-the-box experience as languages like JavaScript, Racket, or Pharo.

I got thinking about this the other day after reading a recent post on r/rakulang. The post's author described themselves as “an old FORTRAN programmer trying to teach himself raku” and asked whether there was any way to use Raku to recreate a bouncing balls demo that seemed like a good learning exercise. The consensus in the replies is that there currently isn't.

And that struck me as a real shame – I decided that there really ought to be a simple and visual way to get write a basic Raku program and see a ball bounce across your screen. So I decided to make one.

The solution: Learn::Raku::With::HtmlBalls

This repo contains the code for a Raku module that allows you to write simple Raku programs to display balls in a web browser. Here's how it works:

  1. Install [Raku] and [Zef] if you don't have them already (I recommend the rakudo-pkg installation method), and make sure you have a recent enough version of Zef to support the Fez ecosystem (you probably do).
  2. run zef --force-test install Learn::Raku::With to install this module. (You shouldn't need the --force-test but, at the time I'm writing this, a bit of deprecated code in Cro means that you do.)
  3. Write a script that imports this module, uses the learn-raku function (described below) to place/move balls, and then sleeps. Then run that script from your shell (e.g., with raku script.raku).
  4. View the balls in your browser at localhost:10000 (or set a different address with the LRW_HOST and LRW_PORT environmental variables).

That's really all there is to it!

The API

The point of this program is to help people learn Raku, not a custom API. So the options for manipulating your balls are deliberately minimalist. Specifically, you get one object (Ball) and one function (learn-raku).

Each Ball has four mutable attributes:

You can omit any or all of these attributes when making a new Ball; any ones you leave out will be filled in with random reasonable defaults.

The learn-raku function accepts three named arguments.

A few more words about the &map-fn parameter. This function will be called 60 times per second with all the Balls that are currently on the screen and its return value (which must be a Ball or a List or Array of Balls) will be used as the Balls for the next frame. Actually, &map-fn can be used in two ways: it can take and return a single Ball, in which case it will be called once on every displayed Ball – this form is convenient if you only have one ball or want all balls to obey the same rule. Alternately, it can take an Array of Balls, in which case it will be called once with the entire Array and should return a new Array or List.

That one function and its three arguments are the entirety of the API in this module – the rest is up to you (and all the power built in to Raku!)

Learn::Raku::With ... examples

The simplest script you can write is using this module is

use Learn::Raku::With::HtmlBalls;
learn-raku :run;
sleep;

This places a single Ball randomly on the screen. Or you could place two overlapping Balls like so:

use Learn::Raku::With::HtmlBalls;
learn-raku :balls[ Ball.new(:x(50), :y(50), :color<#f7347a>), 
                   Ball.new(:x(50), :y(50), :color<rebeccapurple>)],
           :run;
sleep;

If you want a Ball that moves, a simple option would be

use Learn::Raku::With::HtmlBalls;
learn-raku :map-fn(-> $ball { $ball.x += .05; $ball }), :run;
# Remember that you need to return the new ball ^^^^, not just modify one
sleep;

You can check out the examples directory for a few more simple examples. PRs are welcome if you'd like to add more!

Learn::Raku::With ... error messages

The Raku community has a deep commitment to helpful error messages – in fact, we like to say that any error message that's LTA (Less Than Awesome) represents a bug. I really love this approach – especially when first starting out, it's very helpful to have the compiler/interpreter on your side.

So, for this module, I've tried to not only take embrace Raku's approach to awesome errors, but to actually turn it up to 11: I've augmented normal error messages with a bit more color, extracts from your script's source code, and extra info based on the Learn::Raku::With context. For example, in the last section I noted that you need to remember to return a Ball even if you modify one in place. Here's the error message that script would generate if you forgot:

error message for a &map-fn that doesn't return a Ball

Because Learn::Raku::With has more context about how it can be used, it can offer you more info when things go wrong – and hopefully better advice as well. I encourage you to play around and experiment; if things go well, you'll learn something new and if you get an error, you'll probably learn from that as well. If you run into any LTA error messages when using this module, please feel free to open an issue (either with this module for custom error or with Rakudo for the standard error messages it generates).

Learn::Raku::With ... your REPL

Speaking of playing around and experimenting, part of my goal for Learn::Raku::With was to build something that you can use from Raku's REPL (which you can access by running raku without any arguments on the command line or, most likely, from inside your editor/IDE of choice).

And, sure enough, the using the same API described above in your REPL Just Works™. Once you've run use Learn::Raku::With::HtmlBalls in your REPL session, you can call learn-raku just as you normally would – except that now the effects of your each function call are immediately reflected in your browser and certain errors that would end execution of your script just return you to the REPL prompt. Pretty much the only downside to working in your REPL is that, without line numbers to work from, Learn::Raku::With can't print the exact code line of your error – but you probably just typed it in anyway!

My hope is that learning Raku in a REPL-friendly way will help shorten your feedback loop and give you something that approaches true interactive development.

Learn::Raku::With ... the source code

I also hope that the source code for Learn::Raku::With can serve as a learning resource for more intermediate/advanced Rakoons. One problem I've often run into when learning new programming languages is that finding "medium" example programs can be a bit tricky. It's easy enough to find small programs that are well written (for example, on Rosetta Code or similar sites). And the language compiler or major frameworks or tools typically provide excellent examples of large programs. But finding a smallish-but-not-tiny program – one that's small enough to wrap your head around when you're still learning, but big enough to learn more advanced patterns – can be a bit more challenging.

I hope that Learn::Raku::With can fit in that middle category. Not counting error handling, testing, or the HTML template, the program is contained in a single file that's shorter than this README. (At release, it's 118 lines of code + 32 comments + 25 blank = 175 total lines.) I've also done my best to use a simple (arguably simplistic?) design – or at least as simple as possible for a highly concurrent program. The program's high-level design is described in the architecture.md document in this repo, but the short version is that it's essentially a (very) simplified version of Phoenix LiveView that streams JSON to a web browser at 60 fps – something it can only get away with because it's designed to be run locally rather than over an HTTPS connection.

Learn::Raku::With ... other Rakoons

Tight feedback loops are great, but learning is an inherently collaborative process. If you get stuck, please ask for help – either by opening an issue here, asking on the #raku IRC channel (I'm codesections on IRC and pretty much everywhere else), or by posting a question to StackOverflow (the Raku tag is mostly watched/moderated by Rakoons and thus tends to be a friendlier corner of the site).

And if you learn something from Learn::Raku::With or build something cool, I'd love to hear about it. It might make a good example to add to the examples folder, or it might just be a neat demo. But, either way, I'd be interested to see what you create.

Happy hacking!