What is pure function?

What is pure function?

What is pure function? According to Wikipedia:

  1. The function always evaluates the same result value given the same argument value(s). (…)
  2. Evaluation of the result does not cause any semantically observable side effect or output (…).

The first point seems to be clear. It’s a ‘natural’ definition of a mathematical function we learn in the primary school. When can a function yield a different result given the same arguments? Only when it calls impure functions or depends on the external state in the calculations.

The second point mentions semantically observable side effect or output. First of all, what does semantically observed stand for?

Semantics is a branch of science that deals with meaning – a connection between a symbol and something in our senses or mind that the symbol expresses. We associate the word bird with a flying animal covered by feathers. In a Java program, we know that the + symbol stands for addition of numbers or concatenation of strings. Note that this is not the same algebraic operation; numeric addition is commutative, string concatenation is not.

So, for me, semantically observed means (pun intended) being significant in our program.

What is then a side effect? When we modify a global variable, we cause a side effect. Same with calling a setter on an object passed to us. Writing to a file is usually considered a side effect too. Global variables, all living objects during the execution of a program, current content of the filesystem – it’s all state. Side effects are changes to the external state from the perspective of a function that will stay visible after the function is executed.

Let’s see some examples (in ES6). It this function pure?

array => {
  array.reverse();
  // more transformations of the array
}

It uses the Array.reverse method that works in-place. Array object passed to the function is going to be modified – we are changing the external state of the function. Final verdict – we are dealing with an impure function.

Another, slightly modified version of this function:

array => {
  const clone = a => a.slice(0);
  const reversed = clone(array).reverse();
  // more transformations of the array
}

It makes a (shallow) copy of the array argument before mutating it. Assuming that subsequent array transformations are pure, i.e. they don’t mutate the array elements, this function can be considered pure. Seen from the outside, there is no modification of state. array, the only element of the external state known to our function, remains unchanged.

Conclusion

If you want to be pure, don’t get your hands dirty with the outside world:

  • don’t rely on it in your calculations (point 1)
  • don’t try to change it (point 2).

Additional reading

Advertisements

Coordinated Mocha setup and teardown

Playing with Node.js, Express and WebDriver I spotted duplication in my Mocha tests. Each test started/stopped an Express application and created/destroyed a WebDriver client:

before(() => {
  startServer();
  createWebdriver();
});

after(() => {
  stopServer();
  destroyWebdriver();
});

var server, driver;

const startServer = () => server = app.listen(3000);
const stopServer = () => {
  var deferred = Q.defer();
  server.close(() => deferred.resolve());
  return deferred.promise;
};

const createWebdriver = () => {
  driver = new webdriver.Builder()
    .forBrowser('firefox')
    .build();
};
const destroyWebdriver = () => driver.quit();

Obviously, I could move startServer/stopServer and createWebdriver/destroyWebdriver pairs to a separate module and require them in each test. This would have partially solved the duplication, since those methods were defined only in one place.

However, test setup and teardown methods (before and after) are still duplicated in each test case. They share the state (server handle and WebDriver client) and are sequentially coupled. Each launched server instance must be shut down. Same with the WebDriver client. Moreover, I cannot separate setup and teardown steps and reuse e.g. only the server launch.

How can it be solved?

First, you can have more then one Mocha setup and teardown lifecycle function.

Second, statements in anonymous functions passed to before and after are coincidentally cohesive. They have been put together only because they need to be executed at the beginning/end of the test case. This is equivalent to the previous snippet:

before(() => startServer());
before(() => createWebdriver());

after(() => stopServer());
after(() => destroyWebdriver());

Third, functions in JavaScript are first-class citizens. They can be passed around and executed in a different context.

Knowing all this, what’s the final solution?

Coordinate cohesive setup/teardown code in a module. Pass setup and teardown functions to the module and execute them when creating the module instance. Export created or initialised objects if your test methods have to use them.

And the refactored code:

// in test
require('./server')(before, after);
const {driver} = require('./driver')(before, after);

// server.js
module.exports = (setupFn, teardownFn) => {
  var server;

  const startServer = () => server = app.listen(port);

  const stopServer = () => {
    var deferred = Q.defer();
    server.close(() => deferred.resolve());
    return deferred.promise;
  };

  setupFn(() => startServer());

  teardownFn(() => stopServer();
};

// driver.js
module.exports = (setupFn, teardownFn) => {
  var driver;

  const createWebdriver = () => {
    driver = new webdriver.Builder()
      .forBrowser('firefox')
      .build();
  };

  const destroyWebdriver = () => driver.quit();

  setupFn(() => createWebDriver());

  teardownFn(() => destroyWebdriver());

  return {
    driver: () => driver
  };
};

Notice, that in the original code, driver was a WebDriver client instance (an object with properties and methods). After the refactoring, driver is a function that returns the WebDriver client from the module instance. I cannot expose the WebDriver client directly (i.e. as return { driver: driver }). because after the module evaluation it is still undefined.

Conclusion

Passing Mocha lifecycle functions around removed duplication, put sequential coupling under control and allowed composability of test setup and teardown routines.

Serve JSONP in Dyson

Dyson is a great fake JSON server written in JavaScript/Node.JS.

In my current pet project, I have a fake Strava API server. Strava REST API allows you to use JSONP to overcome cross-domain restrictions. You have to add a callback parameter to the query string.

To simulate it with Dyson, you have to override the render method of the Express middleware in the endpoint definition. In my solution, depending on the existence of the callback parameter, I return either raw JSON response or I wrap it with the provided callback:

IGN – Google Maps integration library

What is IGN?

IGN stands for Instituto Geográfico Nacional (National Institute of Geography), a public institution in Spain. Its functions include maintaining spatial data and to producing topographical maps of the country.

What maps does the IGN offer (that are interesting for outdoor activities)?

  • topo maps in 1:1,000,000, 1:200,000 y 1:50,000 and 1:25,000 scales
  • satellite imagery from Landsat 7 and SPOT 5 satellites
  • PNOA aerial imagery (PNOA – Plan Nacional de Ortofotografía Aérea, National Plan of Aerial Orthophotography)

How can I get the maps?

You can see rendering differences between SigPac and Iberpix on the picture below:

Why another viewer?

My idea was to display IGN map tiles on Google Maps canvas by implementing a custom (Google Maps) map type. In this way I can use Google Maps API to draw waypoints, paths, etc. If you mix it with Garmin Communicator Plugin API, you get a full-blown outdoor trip planning tool like Garmin MapSource, written entirely in JavaScript. Ok, there are maps of Spain for Garmin devices (Garmin’s Topo Spain, free Topo Hispania), but they IGN maps are more vivid and differentiate better between paths, tracks and forest roads.

What is IGN-Google Maps integration library?

Currently, it is not a full-feature viewer. The library offers a custom google.maps.ImageMapType, consisting of a google.maps.Projection and google.maps.ImageMapTypeOptions

I took a different approach than taken e.g. by Wikiloc. I didn’t want to make the IGN tile layer interchangeable with maps offered by Google. It means that for a given zoom or scale, you cannot switch between a Google map and IGN map and get the same view. This is possible in Wikiloc, but at expense of correct visualization and smooth zooming. I wanted just to have an independent IGN map viewer implemented in Javascript (ok, you depend now on Google Maps API that is closed source).

The source code has a comprehensive test suite implemented with Jasmine. Doing BDD on a broader scale and in Javascript was a completely new experience for me. With Jasmin it makes fun – the library is intuitive to use and well documented. As a bonus you get a mocking framework – no extra libraries required.

There are some TODOs in the project (they are described in README.md). On the next days I’ll try to fix them, depending on my spare time.

Where can I get the library?

I just published the very first version on the Github: https://github.com/mgryszko/ign-gmaps. The API is not stable yet and may change in the future.

How is it licenced?

MIT licence. You are free “to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software” = fork it and hack on it.

What are next steps?

I’d like to use it in Abredatos 2011 contest. Abredatos is a 48-hour programming challenge. You are supposed to developed a working application making use of at least one Spanish public datasource. It will be held on May 7th-8th 2011.

My idea is to develop the previously mentioned track & route manager with IGN maps and Garmin integration. If you want to participate, drop me an email/tweet.