An introduction to Gloss pt. II: Our first app

Welcome to the second part of this introductory series on Gloss. If you haven’t already, I recommend checking out part I, where I give more of an overview of what Gloss is, and a bit of my motivation behind it.

To cut a relatively short story even shorter, Gloss is just like Ruby, but with a bit more!

The task at hand

If you came here hoping for a To-do list — I am sorry to disappoint. Though hopefully after this you will have the know-how to use Gloss to create one, if you were so inclined. Instead, I am going to be creating a simple Roman numeral parser, in the form of a CLI— here are some basic specs I made for myself:

And some test cases:

Getting set up

Firstly, let’s make a new directory (I am calling mine onefiveone) and cd into it. We’ll need a Gemfile , so we can list our dependencies (in this case just a single one 😁)

Now we can run bundle install to install Gloss, followed by gloss init to set up this directory as a gloss project. You’ll notice that the latter creates a .gloss.yml file in the directory, which lists the project’s preferences. Here, I have added a bit of explanation on each one:

Let’s set these to something we are happy with, and hopefully that should give us a bit of structure to work with:

So we have said we will be working from the src directory, with app.gl as our main entrypoint, so we can go ahead and create those.

Writing our code

This also gives us a chance to think about the components we’ll need, so we can break things down a bit more. Firstly, we’ll need a means of interacting with the user, via some sort of interface. We’ll also want a piece which handles to logic of actually calculating the result, and then also some means of repeating this an arbitrary number of times, so that the user can keep inputting numerals. On top of that, we will probably need some sort of “glue” to bind all of our components together.

Why not start with our interface for interacting with the user, because this can be a fairly simple wrapper around a few core methods:

As you can probably tell, this is pretty close to Ruby! The main differences here being that we are specifying types for the parameters and return types of the input and output methods. Of course, when the behaviour of the two methods is as simple as this, it is hardly much better than just calling gets and puts on there own — but where would the fun be in that?

Next, we could probably start thinking about the actual logic we want to use to evaluate our numerals. We’ll want a distinct component for this, which accepts a numeral in the form of a string, and can output the value as an integer. We’ll also need a way of storing the values of each character. Let’s look at some code, and then discuss what’s going on:

The two main parts worth discussing here are generate and calculate_subgroup_total ; the way I decided I wanted the logic to work was to look through each of the numeral’s characters, and if the next value is lower than the current numeral’s value, then the next value is added to the current numeral, to give a total. If, on the other hand, the next numeral was higher, the logic would act in reverse, and the current numeral would have to be subtracted from the next numeral. I kept track of cases like this by having an array called an atomic subgroup, so that successive numerals could be accounted for.

Consider the example of XI vs IX ; in the first case, I is smaller than X , so it gets added to X to give 11. In the second case, X is bigger than I , so I gets subtracted from X to give 9. In the context of the code above, I would be keeping track of a “subgroup” of [ "I", "X" ] , for which the usual logic of successive addition would be reversed. So generate , therefore, contains the master loop and tracks the total of the characters as it goes, and calculate_subgroup_total handles the logic of any “reverse” sequences.

Is this a perfect algorithm? Not exactly! There are some ways it could trip up — plus it allows for potentially ugly combinations such as IIIIIX — but it satisfies my fairly lenient specs, and it’s good enough for the purposes of this exercise!

You may also notice the require_relative "errors" at the top of the file; so let’s add that file, so we can define some custom error classes which we can raise and handle:

Nothing too fancy here, but this just means that we can have a set format of error message every time we want to use it, and it also means we can easliy categorise errors in our error handling.

This brings us neatly onto the final part of our app: the main glue, in our entrypoint src/app.gl . The main requirements here are that we have a means of allowing the program to repeat itself, so that the user can use it many times over; in addition, we can also specify some behaviour in the case of hitting an unexpected character, or when the user interrupts execution with ctrl-c .

That’s it for the code! Now that everything is written, we can run gloss build to compile these files and generate our ruby output. We can then run it with ruby app.rb to see the fruits of our labour in action 🤩

I also translated my specs and test cases into specs for rspec , to give reliable confirmation that things were working as they should; and it is highly satisfying to see it when they do 🥳

That’s everything here for now — thanks for bearing with me if you have made it this far! Be sure to check out the final code on GitHub below, and stay tuned for more updates, where we will use Gloss for writing and deploying our first web app 😁 🚀