This short series of posts will concern itself with using Common Lisp and Ada to create a simple omer count application. Common Lisp is used to incrementally and interactively generate what is effectively a working code specification of the required functionality. A prototype, in other words, but one which itself defines the functional requirements of the application. This is what may be called an executable specification, fully documented by the working source code.
Using code as documentation is a powerful language-based idiom, against which we may contrast essentially picture-based idioms such as the use of UML diagrams.
After the Common Lisp prototype is complete, a more formal implementation in Ada will be designed and coded according to the Lisp specifications, resulting in a compact, standalone executable program which produces the same output as the Lisp.
The purpose of the exercise is to explore in microcosm how well Lisp and Ada can work together to engineer a solution to a problem.
There is a small issue, though. I don't know Ada. Well, it's not entirely true, since I remember programming a network battleship game in Ada 95 about a decade or more ago, while my son did a network protocol compatible version in Python. Since then, there have been two major updates to Ada: 2005 and 2012. So I'll be learning Ada along the way. I have ordered John Barnes' Programming in Ada 2012 (*), which I am now waiting to receive for the second time, due to it being damaged in the mail <sad face/>.
It is said that a software engineer is a software engineer first, and a programmer of a particular language only secondarily, with the implication that the language is learned a lot more easily and quickly than the engineering. We'll be putting that little pearl of wisdom to the test! <smile/>
(*) The link is to Amazon, but I purchased my particular copy elsewhere.
What is an Omer count anyway?
There is the word 'eclectic' in the title of the blog, right? So what better way to kick off than with a little example about something that no one's ever heard of? Well, that's not quite true, as you will see.
The biblical people of God, called the Hebrews, the Israelites, the House of Israel, or most often simply, the Jews, have two feasts---among others---called Pesach (which is Passover) and Shavuot (which is Pentecost). The Passover holy day is on the fifteenth day of the month of Aviv, and Pentecost falls fifty days after that --- hence the English name, which comes from the Greek, and meaning 'fiftieth'. Counting the fifty days from Passover to Pentecost is often called the "Omer Count" because an omer is a measure used for grain, and since Pentecost and Passover occur during the northern hemisphere Spring harvest time, and Pentecost in particular is often referred to as a harvest festival.
The Scripture gives a couple of particular instructions on the counting from Passover to Pentecost:
- The counting is to begin (from one) on the day after the Passover Sabbath on 15 Aviv.
- The days from one to forty-nine are to be counted, and then the fiftieth day is to be celebrated as the day of Pentecost.
- The celebration of the fiftieth day is to begin at sunset of the previous day.
- The seven weekly Sabbath days along the way are also to be separately counted.
- Each of the seven weeks is to be counted.
We take it that to do this counting, the intention is that it be done each day until the eve of Pentecost arrives; and therein lies the problem which this program is meant to solve: a single person performing this count manually each day may possibly be error prone, especially if done first thing in the morning while still sleepy <grin/>. It's handy to have a convenient confirmation that one has not skipped or doubled up on a day, as well as to have a usable textual notice that can easily be copied and pasted for sending off to friends as a reminder.
So, it's quite a trivial little example which may better be called a script than a program or application, but it serves well as a first experiment with the whole Lisp to Ada design methodology.
The normal output desired is like the following sample:
This demonstrates the following requirements:
- The heading in upper case, containing the day of the week as a non-abbreviated English word, and the date in ISO 8601 numeric date format as shown.
- The first line of the output body shows the number of days out of fifty to Pentecost, which is referred to as 'Shavuot' (meaning 'weeks').
- The second line of the output body shows the number of days remaining.
- The third line of the output body shows which day of which week since Passover ('Pesach'). Note that this does not correspond to normal calendar weeks, as Passover can be on any day of the week.
- The fourth and last line of the output body shows the number of weekly Sabbaths (Saturdays) counted up to and including the given date.
- Except for the date, there are no printed numerics. All numbers are written out in words, including ordinals (first, second, third, etc.).
- Singulars and plurals must be printed correctly. For example, we do not want to see, "There are one more days to go!", but instead, "There is one more day to go!"
If the output is for a Saturday, the content is varied slightly, as follows:
That demonstrates the following additional requirements:
- The "SATURDAY" is replaced with the word, "SABBATH".
- The last line of the output reads, "It is the xxxth of the Sabbaths!", where xxxth is 'first', 'second', 'third', ... , 'seventh'.
There are four outlier or boundary cases which we also want to handle:
- The date of Passover itself is not included in the count. If the count is requested for this date, the output should be as per: "2016-03-25 is Pesach. Fifty more days to Shavuot." Obviously, the date shown will vary from year to year, since Passover is defined according to lunar months and not Gregorian calendar months.
- The date of Pentecost (Shavuot) itself is also not included in the count. If the count is requested for this date, the output should be as per the following:
- Obviously, any date after Shavuot is also not included in the count. If the count is requested for any date after Shavuot, the output should be, "Sorry, but you have missed Shavuot! :-("
- Equally obviously, any date prior to Passover is not included in the count. If the count is requested for any date before Passover, then output, "You have confused me." Or else some informative but boring message explaining that the omer count does not begin until after Pesach.
Note in passing that the dates given in the examples were the actual dates for 2016. For the benefit of those who may know that the Jews kept those feasts one month later in 2016, the reason is that the Jews now follow an imprecise, precalculated calendar which is slowly drifting with respect to the true solar year. The accumulated error in the Jewish calendar caused all of their feasts to be one month late this year, as a result of intercalating an extra (leap) month in the wrong year.
Preparing to develop the Common Lisp version
It is assumed that if you wish to work with or run the Lisp code, then you will already have a Common Lisp development environment set up. I am personally using and recommend the combination of Emacs and SLIME as a development IDE on Linux, together with the latest release of SBCL or CCL as the Common Lisp implementation. If you are new to Common Lisp, then it may be less trouble to get started with LispWorks or Allegro Common Lisp. Details of how to do this are beyond the scope of this article. All of these options will work on Linux, Windows or Mac.
In the next part, we will look at what was involved in developing the Lisp version of the program interactively and incrementally, and the full source will be presented so that those who wish to run it or modify it are able to do so. The script was actually programmed back earlier in the year, in March or April, so there will be a bit of reconstruction from memory involved.
The Ada version, however, has not yet been developed, so we will be able to see what it looks like moving from a simple Lisp example program and implementing this in Ada, which is the main purpose of these posts. A small extra challenge will be learning Ada along the way! :-)