NOTE: This is a direct followup of the previous post. Read that first then come back here.

Glowdust so far seems like a confused programming language or, at best, a tuple store that let pattern matching get to its head.

The answer to both is yes, even when there was no question asked. That’s how confused it is.

But my intention is not to create a towering construct of algebraic elegance that makes data storage and retrieval a sublime experience that reduces to tears of joy all who gaze upon its marvelous form.

Well, perhaps by accident.

Instead, I’ll settle for having some fun and maybe learning something in the process. Let me try, then, to add some query functionality to it, see what happens.

Where we’re going, we’ll need a new operator

Say I have a temperature sensor and I store its minute-by-minute measurements, in Glowdust

define temperature(1) = 15  // in minute 1, temperature was 15 degrees
define temperature(2) = 15
define temperature(3) = 14
define temperature(4) = 13
define temperature(5) = 12
define temperature(6) = 13
...

The first query I want to run is “at what minute was the temperature 13 degrees?”

To rephrase, find me a value, x, for which temperature(x) = 13.

To write this, I introduce the -> operator, named pass, for now. With it, the query is written as

x -> temperature -> 13 return x

-> “feeds” values from the left hand side to the right hand side. The rhs looks up the incoming value and outputs the function value. In this example, x is free, but the query is answerable because we know the domain and codomain of temperature. Semantically, x will run the full range of possible values for Integer, feed each one into temperature and match the produced value against 13. Whenever that matches, it returns the value for x. The output is a (possibly empty) sequence of tuples, of arity 1 in this case.

I can combine -> chains with predicates. Here’s how I would find at what minutes the temperature was between 14 and 16 degrees

x -> temperature -> result WHERE result >= 14 AND result <= 16

I don’t like WHERE at all, but it will have to do for now. It will be the first one to go.

But here’s a neat thing - the semantics of the WHERE clause as written above fit the -> construct.

>=, <= and AND are all functions. In this example, >= and <= both are of type (Integer, Integer) -> Boolean and AND is (Boolean, Boolean) -> Boolean. This means I can rewrite

result >= 14 as (result, 14) -> >= -> true

and

result <= 16 as (result, 16) -> <= -> true

I can also rewrite, in general

x AND y as (x, y) -> AND -> true

which means I can combine all these to replace the WHERE clause with

((result, 16) -> <= , (result, 14) -> >=) -> AND -> true

and the query would become

x -> temperature -> result, result -> ((result, 16) -> <= , (result, 14) -> >=) -> AND -> true

This may please currying groupies, but it’s unreadable. Semantically it is on the money though, so I feel safe in keeping WHERE around for now.

Compose things

Let’s add another function in the database

define is_high_temp(temp) = { temp > 15 }

temperature and is_high_temp compose, since temperature returns Integer which is the input type for is_high_temp.

I can use this, together with ->, to do a join, of sorts

x -> temperature -> is_high_temp -> true return x

which returns all minutes at which temperature was high. Here I happened to define is_high_temp as a computed function, not stored, but Glowdust doesn’t care anyway, all that matters is the function type.