Awkward ID generation with a DCG

I work in an industry that likes to use an ID/label/hyperlink notation by combining a letter denoting a parent class with a number: "H-1". The application I'm working on, given a parent class, needs to return the next ID. This shouldn't be too hard if they were sequential, but ID's can be deleted and so the next available ID needs to be returned. In this post, we explore how a DCG can be used to solve this problem.


An ID DCG

As programmers we are given problems to solve, like getting the next available ID. It's all too easy to set about solving that problem without giving due concern to the problem domain. In my experience this often results in wasted time and messy code. Before trying to manipulate something, we should know what that something is. So we begin, as we always should, by telling the truth: we define what an ID is in this domain.

?-

This little DCG can be used to sequentially generate all valid IDs for all valid classes (fruit and vegetable). This means we can also use it to check given IDs are valid, we're using our Prolog: Forwards and Backwards!

?-
?-
?-
?-

A new ID

Now we have defined an ID in context, we can use it to define a new ID. We shall consider a new ID as one that we do not yet know of in our asserted facts:

new_id(Class, ID) :- id(Class, Chars, []), atomic_list_concat(Chars, ID), \+ fact(ID, subClassOf, Class).

This may not be the most efficient manner of coding this, but it sure is easy to reason about, provided you can read DCGs. Here's a complete ID generator:

?-