How to query Glowdust
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.