# Learning from community solutions on Exercism - part 1

There's a relatively new jq track on Exercism, and I've been working through some of the exercises. There are at least a couple of features that appeal to me; one is the ability to easily write and submit solutions from the command line (see Working Locally) and the other is the community solutions that are available to you after you submit your own first solution.

As well as the direct benefit of practice, I've learned and been reminded of aspects of jq while looking through the community solutions. So I thought I'd write some of them up here, because writing will also help me remember.

## Shopping List exercise

Even in the basic learning exercise Shopping List there are subtle points worth talking about.

It's based on determining information from a shopping list, that looks like this (reduced for brevity):

``{  "name": "Ingredients for pancakes",  "ingredients": [    {      "item": "flour",      "amount": {        "quantity": 1,        "unit": "cup"      }    },    {      "item": "sugar",      "amount": {        "quantity": 0.25,        "unit": "cup"      }    },    {      "item": "baking powder",      "amount": {        "quantity": 1,        "unit": "teaspoon"      }    }  ],  "optional ingredients": [    {      "item": "blueberries",      "amount": {        "quantity": 0.25,        "unit": "cup"      },      "substitute": "chopped apple"    }  ]}``

The first observation is about the contrast between the concept of arrays, with corresponding array functions like `map`, and the concept of streaming in jq.

The third task in this exercise was to identify the amount of sugar, which I determined like this:

``(  .ingredients   | map(select(.item == "sugar"))   | first.amount.quantity)``

The value of the `ingredients` property is an array, and using `map` like this produces another array, albeit with a single element (the object that represents the sugar ingredient). So I then used `first` to grab that element, and navigated to the `quantity` property). All fine. Having used `map` in various languages, and learned to think about arrays and how functions such as `map`, `filter` and `reduce` work (see FOFP Fundamentals of functional programming) this felt natural to me.

That being said, jq is fundamentally stream oriented, which can be seen in glennj's solution:

``(  .ingredients[]  | select(.item == "sugar")  | .amount.quantity)``

Note the use of the array / object value iterator on the `ingredients` property (`[]`), and the lack of `map` (and `first`).

Expressing `.ingredients[]` (as opposed to `.ingredients`) explodes into a stream of values (one for every array element) which are each passed downstream (to `select` and beyond). The `select` then only allows the journey to continue for the element(s) that satisfy the condition, which means that the data coming through the last pipe is not an array but an object*.

*theoretically there could be more than one object coming through, but in this case there is just one.

Streaming in jq is an important aspect and can be a powerful mechanism to use.

## Assembly Line exercise

Assembly Line is another learning exercise, where I decided to avoid an `if ... elif ... else ... end` structure and instead encode the computation for task 1 (calculation of the production rate per hour) using an array as a kind of lookup table:

``def production_rate_per_hour:  . as \$speed  | (221 * \$speed)    *     ([0, 100, 100, 100, 100, 90, 90, 90, 90, 80, 77][\$speed] / 100);``

I prefer the way this looks, over a multi-condition `if` structure, but there's a further improvement possible that I picked up, again from glennj in his solution, which was the avoidance of the symbolic binding of the input to `\$speed` (the `. as \$speed` part).

I'd used a symbolic binding because I knew I would need to refer to it both in the basic speed calculation (multiplying it by 221) and using it to index into the lookup table (`[\$speed]`). But glennj reminded me that I could just as easily have used `.` directly:

``def production_rate_per_hour:  . * 221 * [1,1,1,1,0.9,0.9,0.9,0.9,0.8,0.77][. - 1];``

Note that tHE subtraction of 1 from `.` here is because this lookup table was constructed without a dummy value of 0 for the theoretical 0 speed.

A useful reminder which helps me strive for better avoidance of all that is unnecessary.

## High Score Board exercise

In reviewing my solutions for this post, I came upon what I'd written for the last task in the High Score Board exercise, which was to find the total score, as illustrated thus:

``{  "Dave Thomas": 44,  "Freyja Ćirić": 539,  "José Valim": 265}| total_score# => 848``

I'd written the following:

``def total_score:  [.[]] | add + 0;``

As I mentioned earlier in this post, `.[]` is the array / object value iterator. When I mentioned it back then, it was used to iterate over array values, i.e. the elements of the `ingredients` array.

Now here it's being used to iterate over the values in an object. Not the keys, but the values, i.e. `44`, `539` and `265`. When I looked at it, I was reminded of the jq manual section on map and map_values which says:

`map(x)` is equivalent to `[.[] | x]`. In fact, this is how it's defined. Similarly, `map_values(x)` is defined as `.[] |= x`.

Also as I mentioned earlier, this iterator will create a stream of values, rather than an array. In other words, this:

``{  "Dave Thomas": 44,  "Freyja Ćirić": 539,  "José Valim": 265}| .[]``

produces:

``44539265``

Note the lack of any semblance of an array - these are all single JSON values.

So in order to be able to use `add`, which takes an array as input, I therefore also had to wrap this in an array constructor i.e. inside square brackets `[ ]`:

``{  "Dave Thomas": 44,  "Freyja Ćirić": 539,  "José Valim": 265}| [.[]]``

which gave me:

``[  44,  539,  265]``

Anyway, forgetting this `.[]` was acting as an object value iterator, I then thought "hmm, this is more or less the equivalent of `map`", given what the manual stated ... so I replaced `[.[]]` with `map(.)`, like this:

``{  "Dave Thomas": 44,  "Freyja Ćirić": 539,  "José Valim": 265}| map(.)``

This also gave me an array:

``[  44,  539,  265]``

But the interesting thing was that this is `map` being applied to an object, not an array, and I'm guessing it does the right thing in a sort of DWIM way (which I first came across in Perl). Even more interestingly, this use of `map` on an object, which produces an array of the values in that object, contrasts nicely with `map`'s sibling `map_values`, which, perhaps confusingly, doesn't do that.

In fact, I used `map_values` in addressing the previous task in this exercise, to apply Monday bonus points, which I did like this:

``def apply_monday_bonus:  map_values(. + 100);``

What `map_values` does is return the object but offer you the values to manipulate as each property is iterated over. So this:

``{  "Dave Thomas": 44,  "Freyja Ćirić": 539,  "José Valim": 265}| map_values(. + 100)``

produces this:

``{  "Dave Thomas": 144,  "Freyja Ćirić": 639,  "José Valim": 365}``

and not this:

``[  144,  639,  365]``

To complete the picture on this observation, I thought I'd mention the `+ 0` part in the solution:

``def total_score:  [.[]] | add + 0;``

If you supply an empty array to `add`, it will produce `null`:

``[] | add# => null``

According to the addition section of the jq manual:

null can be added to any value, and returns the other value unchanged.

## Vehicle Purchase exercise

The Vehicle Purchase exercise is another learning one and was quite straightforward. My solution for the first task ("Determine if you will need a drivers licence") looked like this:

``def needs_license:  . == "car" or . == "truck";``

While this is fine because there are only two possible values for which we want to return true, the way I expressed this bothered me slightly.

In JavaScript, for example, I would have used an array to contain the values, and then used includes like this:

``needs_license = x => ["car", "truck"].includes(x)// needs_license("car") => true// needs_license("train") => false``

So after submitting my solution, I looked at what others had done. Quite a few used the same approach, as me, but there was a solution from IsaacG that looked more appealing.

### Considering the inside filter

``def needs_license:  [.] | inside(["car", "truck"]);``

This `inside` filter looked to me like the JavaScript approach above. But my goodness, did it open up a rabbit hole of investigations!

Looking at it, one would think that this would do the job. I started looking at the definition of inside in the jq manual, and found that it was "essentially an inversed version of `contains`". Before looking at the definition of `contains`, I took a quick look at some of the examples, and saw this one, which made me scratch my head:

``jq 'inside(["foobar", "foobaz", "blarp"])'Input:	["baz", "bar"]Output:	true``

This is not an element-wise check, it's a (sub)string based comparison, even when working with arrays.

I looked at contains and the examples and description had me more convinced that actually the use of `inside` in the solution to this sort of task may not be ideal.

There's a sentence in the description of `contains` which looks fairly innocuous, but in fact masks a major gotcha (emphasis mine):

[With `A | contains(B)` ...] an array B is contained in an array A if all elements in B are contained in any element in A.

### Digression: inside as inverse of contains

Before continuing, let's just understand what does "inside is an inversed version of contains" mean? Well, we can look at the source for `inside` in `builtin.jq`:

``def inside(xs): . as \$x | xs | contains(\$x);``

We can see that this is effectively just switching around the two arguments - here, `xs` is the absolute list of elements, and `.` (which is bound to `\$x`) is what we want to look for.

### What's the issue?

OK, digression over. Clearly, given the relationship between `inside` and `contains`, the gotcha also applies to `inside`.

To help me focus in on the significance of "if [...] elements [...] are contained in any element [...]" in the above description, I defined the two licensable vehicles as being "cart" (with a "t") and "truck" instead of "car" and "truck":

``def licensable_vehicles: ["cart", "truck"];``

I then recreated the function above to look like this*:

``def needs_license_inside: [.] | inside(licensable_vehicles);``

I then tested it with three vehicles, which gave me an unexpected result:

``["bus", "cart", "car"] | map(needs_license_inside)# => [false, true, true]``

The `inside` function returns `true` for "car" ... because the string is contained in one of the elements ("cart"). We can even unpick the inverse, to get closer to the source of the problem:

``licensable_vehicles | contains(["car"])# => true``

Yikes!

### Some alternatives

Rather than bemoan the slightly vague documentation combined with my misaligned expectations, I thought I'd look into how one might go about testing membership, if `inside` (or `contains`) is not the way.

#### Using any(condition)

The any filter has different forms (I guess known as `any/0`, `any/1` and `any/2`). We can use the `any/1` form with a condition, like this:

``def needs_license_any: . as \$v | licensable_vehicles | any(.==\$v);``

This will give us what we're looking for:

``["bus", "cart", "car"] | map(needs_license_any)# => [false, true, false]``

By the way, I had first created this version of the function as follows, and passed the vehicles under tests via a parameter:

``def needs_license_any(\$v): licensable_vehicles | any(.==\$v);["bus", "cart", "car"] | map(needs_license_any(.))# => [false, true, false]``

But inspired by the builtin definition of inside I felt OK in using a symbolic binding (`. as \$v`) after all, despite what I mentioned earlier in the section on the Assembly Line exercise.

#### Using index

In the jq manual, index is described in a vague way, and the examples are quite minimal, which might give the impression it relates to strings and substrings. But I'm learning that the limited examples can be deceiving, and the functions and filters have subtle depths and for the most part just work the way you might assume they might, in different circumstances.

Here, `index` will work for us in that it can return either an array index (for a given element, if it exists) or null (if it doesn't). A simple start with `index` might look like this:

``def needs_license_index: . as \$v | licensable_vehicles | index(\$v);``

However, this doesn't quite give us what we want:

``["bus", "cart", "car"] | map(needs_license_index)# => [null, 0, null]``

But anding values such as these with `true` does the trick, of course:

``def needs_license_index:   . as \$v | licensable_vehicles | index(\$v) and true;["bus", "cart", "car"] | map(needs_license_index)# => [false, true, false]``

Note that in jq:

false and null are considered "false values", and anything else is a "true value"

which is why `0 and true` evaluates to `true`.

I'm sure there are more options, but I'll leave it there for now. What is your goto approach for checking for elements in arrays? Let me know in the comments.