Jez Higgins

Freelance software generalist
software created
extended or repaired


Older posts are available in the archive or through tags.

Feed

Follow me on Twitter
My code on GitHub

Contact
About

Thursday 31 August 2017 Functional Programming with Rillet: Roman Numerals

const of = require('./rillet.js').of;

function roman(number) {
  return of('I').cycle().take(number).join('').
    replace(/IIIII/g, 'V').
    replace(/IIII/g,  'IV').
    replace(/VV/g,    'X').
    replace(/VIV/g,   'IX').
    replace(/XXXXX/g, 'L').
    replace(/XXXX/g,  'XL').
    replace(/LL/g,    'C').
    replace(/LXL/g,   'XC').
    replace(/CCCCC/g, 'D').
    replace(/CCCC/g,  'CD').
    replace(/DD/g,    'M').
    replace(/DCD/g,   'CM');
} // roman

Here's another little bit of functional programming silliness that, again, I've adapted from some Clojure I found in a tweet -

I mentioned before that Lisps are inside out which, of course, this example is almost designed to show off. My JavaScript version is, I submit, undeniably easier to read and understand.

Presentational issues aside, this way of calculating Roman numerals is new to me and I love it. I was given a close cousin of this problem, given a cash amount find the smallest number of notes and coins needed, as coursework for my CSE in Computer Studies back in 1984. I solved that using repeated subtractions, and that's probably where I'd start today. This approach, treating it as a string substition problem, while not necessarily "efficient", is just beautiful.


Tagged code, rillet, javascript, and fp

Friday 25 August 2017 Functional Programming with Rillet: FizzBuzz

const rillet = require('./rillet.js');

const { of, zip, numbers } = rillet;

const fizzes = () => of('', '', 'Fizz').cycle();
const buzzes = () => of('', '', '', '', 'Buzz').cycle();
const words = () => zip(fizzes(), buzzes()).map(([f,b]) => `${f}${b}`)

const integers = () => numbers(1);

const fizzbuzz = (howMany) =>
        zip(words(), integers()).
        map(([w, n]) => w ? w : n).
        take(howMany);

fizzbuzz(100).forEach(console.log);

After writing about Eliza, I'm revisiting FizzBuzz, another programming classic. Functional style FizzBuzz are, when you first see one, a little bit vexing - where are the loops?, where's all the if statements? - but that's part of what's makes them fun and interesting. What I've put together here in JavaScript using Rillet.js could have been written in pretty much any modern language and look pretty much the same. There's only one real JavaScriptism in the whole thing - w ? w : n - which selects a word or a number. Since empty strings in JavaScript are falsey (other, saner, languages disagree), we can use test it directly in the conditional rather than having to compare it with anything.

This little exercise was triggered by this tweet, which is a Clojure version.

There has a couple of extra steps compared with my version, replacing empty strings to nils (which I now think might be unneccessary) and converting integers to their string representations, but the essential elements are the same
  • Create an infinite sequence with the word 'Fizz' every third item
  • Create another infinite sequence with the word 'Buzz' every fifth item
  • Merge those two sequences
  • Create a sequence of the natural numbers
  • Merge those two sequences, using the word if there is one, otherwise the number
  • Pull as many items out of the sequence as you want
  • FizzBuzz!
It's actually a super neat and useful way to think about the problem.

(Of course with Clojure, being a Lisp, everything's inside out. Lispers' contend this is the correct and proper nature of things, but I've always struggled with it a bit. This example isn't so bad actually, but by the time you get to your fifth left bracket it can be really hard to navigate.)


Tagged code, rillet, javascript, and fp

Monday 07 August 2017 Eliza in Python

I don't remember when I first read about Eliza, but it must have been around 1983, probably in an article in Your Computer magazine. Eliza, a program written in 1965, talks to you. Well sort of - it emulates a Rogerian psychotherapist. Rogerian psychotherapy is non-directive, that is the therapist attempts to get the client to do most of the talking, without offering advice or opinion. Obviously it's more subtle than that, but that's the gist.

The idea of being able hold a conversation with a computer seemed incredible. How vast and complex a program it must be. Eliza was, for a while, like a programming holy grail. It was simple enough to describe in a sentence, yet, to my 14 year old brain, seemed impossible to achieve.

In actual fact it turns out to be really rather straightforward and can be written in a just a few lines of code. Here's a version of Eliza written in Python that I bundled up from someone else's initial work shortly after the turn of the millenium. It's all smoke and mirrors; the program doesn't have a clue what it is saying and it's not difficult to catch it out, but it's amusing and, in this modern age, it means your chatbot always has something to say.

The eliza.py module includes an interactive mode, so you can get a feel for how it behaves. Just grab the code and python eliza.py. To use the it from with in your own code do something like

import eliza

therapist = eliza.eliza()
while some_condition:
  #get input from somewhere
  reply = therapist.respond(input)
  #send reply somewhere

I'd let this drop of the internet when I rejigged this website, but it turns out it's referenced all over the place including on Wikipedia, so I've resurrected it, updated for Python 3, and popped it up on GitHub.


Tagged code

Friday 07 July 2017 From X to Y

A month or so back I spent a hectic couple of weeks and a client job and have realised I'm now in a position to write one of those 'We reimplemented a piece of software originally written in language X using language Y and you won't believe what happened next' articles. Well, you may well not believe it but you can probably guess it, because articles like that are 10-a-penny and the reported results are always that some problem with the original code was solved in the most wonderful way. That problem could be speed, maintainabilty, memory use, lack of suitable job applicants, almost anything, but you can be sure it was resolved by the simple expedient of chucking out a load of code and writing some new code. The new code is invariably shorter and more expressive, somehow lacking the cruftiness of the old. The author invariably had lots of fun writing the new code, and often declares their chosen language to be their favourite. Frequently the article conclude with a little coda encouraging others to follow suit, or roundly insulting those so blinkered they choose not to.

This is not that article.

It is the case that I replaced a piece of production code developed by several people over a number of months in nine days, by myself. The new code is visibly faster, in the way that people notice without having to run benchmarks and draw graphs. It's leaner too - the VM it deployed to has half the CPU and a quarter of the memory of the previous version. It doesn't time out, exceed its memory quota, or crash.

I must be ace on the old keyboard, right?

Well, perhaps. But if there's any lesson to be learned here, it's that reimplementing a system is generally substantially easier than building it the first time round. In this case, a data access layer for a website, the existing code told me exactly which endpoints I needed to support, and which parameters they took. The productions logs told me which of those endpoints were actually being used, and with which parameter combinations. Almost straightaway, therefore, I knew where to concentrate my efforts, and what I could ignore completely. The existing code had a reasonable set of unit tests, which saved me the bother of having to come up with my own. I was able to look at the existing database queries, and translate them across into my new code. I could examine how the existing code had a addressed a particular issue and evaluate whether I wanted to bring that into the new code. I had the ridiculous luxury of being able to run up the old code and my new code side by side, prod them with the same requests, and compare the results, one with the other.

In short then, I benefited hugely from the fact that the system already existed. There was just a ton of stuff I had to think a whole lot less about, and quite a lot I didn't have to think about at all. Consequently, I was able spend more of my effort thinking about the things that did matter, and the result, unsurprisingly, was less code.

While I rarely suggest an all-out rewrite, I did one here because I was asked to. The language I worked in wasn't my choice, it was the client's. The new code is quicker, not because of any special property of that language, but because I was able to look at the old code, see the inefficencies, and was given time and space to do something about it. If they'd chosen another language, the results would have been similar. Hell, if they'd chosen the same language as before, the results would have been similar. If I'd been left to work on the original code for the same amount of time, I probably could have produced something similar1.

Even when you're throwing it out, there's a lot of value in old code. Be grateful for it.

1. Given their lack of faith in the existing code, I suspect that if I'd suggested just letting me have at it, I may well have been turned down. Had that suggestion been accepted, I probably would have only been given half as much time.
Tagged code

Monday 29 May 2017 Extending Rillet

Since first releasing Rillet.js, my Javascript streams library, back at the start of May, I've carried on working on it and some how managed to produce, at time of writing, a further 10 releases of one sort or another. While some of those are trivial documentation fixes, I have added quite a number of additional terminal methods and a stream modifier too.

The motivation for part of this work has been to provide parity with JavaScript's Array class. If you can do it eagerly with an Array, you should be able to do it lazily with Rillet, hence the addition of every, some, none, and join. I've drawn inspiration (by which I mean copied) from other streams libraries, including .NET's Linq, Java 8 Streams, Python iterators, and my own previous work, which so far has resulted in the max, min, and sum terminators. Lastly, and perhaps most importantly coming as it does from work I've been doing, is the modifier method uniq, which strips duplicates from the stream.

Of course, all modifiers can be written in terms of filter or map, and all terminators can be written in terms of reduce, sometimes trivially so. Here's max

  seq.reduce((a,b) => (a > b) ? a : b, Nill);

and sum, which is even simpler

  seq.reduce((a,b) => Number(a)+Number(b), 0);

Why bother, then? The first reason, and it's a pretty important one, is that's it's simply more expressive. What a call to sum does is pretty obvious, while reduce((a,b) => Number(a)+Number(b), 0), although in no way obscure still requires you to think a bit. This is even more the case for something like

  seq.filter(function() {
    const seen = {};
    return i => {
      if(seen[i]) return false;
      seen[i] = true;
      return true;
    }
  }())....

which is a whole lot wordier, significantly less obvious than

  seq.uniq()....

and also contains a subtle bug. Correctness, then, is another reason. Each time you have to write an extra bit of code, you risk getting it wrong. The more the library can do for you, the fewer bugs you'll write. Finally, there are cases where a specialised implementation can be more efficient. Rillet's none, some, and every can all return early when appropriate, while the same tests expressed in terms of reduce would have to continue until the sequence was exhausted. For most cases I expect the execution time difference to be trivial, but when it does count, it could be significant.

When I first put Rillet together it wasn't really much more than a little demonstration to support my ACCU talk. Rather to my surprise, my recent work has all been in JavaScript, and so I've been using it anger. It's working out rather well so far.


Tagged javascript, fp, code, and rillet
Older posts are available in the archive or through tags.


Jez Higgins

Freelance software generalist
software created
extended or repaired

Older posts are available in the archive or through tags.

Feed

Follow me on Twitter
My code on GitHub

Contact
About