The last feature I have implemented on the NowTV app is a cache that stores a complex data structure, basically a subset of a JSON response containing multiple and nested models.

Let’s consider a basic JSON like the following one:

This JSON in translated in something like

Lately I’m studying theory behind Functional Programming and I was wondering how to access/update data stored in the cache in a functional way. Thanks to manub I ended up in Lenses and even though I’m not expert at all about FP, the aim of this post is just to share what I learned, from a lens newbie perspective :)

Functional Lenses

As we know, in the real world, a Lens is a tool to focus into a part of an image, used alone or in combination with other Lenses (i.e. think to a telescope).

In FP, a Lens is a first-class value that let you having a partial view (just referred as view V) on the internal part of a complex data structure (container C) and it could be combined with other Lenses to create more complex queries over the container.

Basically a Lens is a functional and combinable getter/setter over a complex data structure.

Lenses have been called “jQuery for data types”: they give you a way to poke around in the guts of some large aggregate structure. Lenses compose (so you can make big lenses by gluing together little ones), and they exploit type classes to allow a remarkable degree of flexibility (get, set, fold, traverse, etc). (*)

A Lens on a data type [C, V] is made up by:

get(V): C => V

set(V, C): [V, C] => C

The meaning of these two functions is that you can query on the container C to get a view V and when you set a new value for a particular V in C, you get an updated copy of C (this is one of the FP core concepts: immutability).

Every Lens<C, V> should satisfy these three rules:

1. Lens.get(Lens.set(Va, C)) == Va 2. Lens.set(Lens.get(Va), C) == C 3. Lens.set(Vb, Lens.set(Va, C)) == Lens.set(Vb, C)

set a value followed by a get always returns the value previously set; getting a view from the container and setting it again returns the same container; applying N consecutive set functions on C is equal to set the last value on the initial C;

In this way we have at least a baseline to develop our Lenses without side effects.

Swift implementation

What we want to implement is a data structure that implements the get/set previously defined as

get(V): C => V

set(V, C): [V, C] => C

That is easily translated in the following struct:

get and set are two computed properties that precisely define our functions.

Now what we’d need is the concrete and accessibile of a Lens for every attribute we want to inspect/update (that will be used later in downloaded models via JSON):