1
Student: Sam Foster
Course: CS 2620
Instructor: Professor Cezar Câmpeanu
Date: April 9, 2026
Introduction
In accordance with the goals outlined in my project proposal, the following report represents a
comprehensive examination of the Lucid programming language. As noted earlier, the purpose of this
project is the study of the Lucid programming language as an example of a dataflow program. In contrast
to the modern enterprise languages such as Java or C which operate by using procedural logic, Lucid calls
for a complete paradigm switch in order to enable computation. In a dataflow program, a programmer no
longer needs to worry about the control flow of the central processing unit but needs to concentrate on
transformations within a data stream. In order to make a thorough evaluation of this language, this report
will analyze its history and philosophical principles behind its non-procedural nature; as well as its
technical aspects, such as sequence control and syntax.
Historical Development
In order to better comprehend the process of data processing performed by Lucid, one should first
consider its creation context. In the late seventies of the previous century, Edward A. Ashcroft and
William W. Wadge initially proposed the idea of this programming language while working at the
University of Waterloo.
1
Surprisingly, the initial goals were quite small and did not presuppose developing
a dataflow paradigm from scratch. Initially, the inventors only wanted to demonstrate the possibility of
conducting ordinary programming without using such constructs as assignments or goto-statements.
2
As
for motivation, it was mainly aimed at legitimizing the concept of structured programming in a
2
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language.” p.vii
1
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language.” (London, UK:
Academic Press, 1985) p.vii
2
mathematical sense in order to radically simplify the extremely complicated procedure of verification of
programs.
The development of Lucid into an actual dataflow language was achieved through experimenting with the
definition of iterative states. It became apparent that the dynamic information contained in the loop
variable could be defined mathematically via induction.
3
As a result, the simple replacement of imperative
statements with first and next declarations implied a completely different approach to dealing with
variables and expressions, since those turned out to be an inherent representation of infinite sequences or
histories of data.
4
Once this essential aspect was introduced, nested loops and user-defined functions
appeared to simulate coroutines and continuous filters . Eventually, the inventors came up with the idea
that they had independently developed a pipeline dataflow model similar to the networking concept
described by Gilles Kahn.
5
Language Overview
The key element of Lucid’s architectural design is its stream-oriented and non-procedural nature.
Whereas the computation within imperative programming languages like C and Java is based on the von
Neumann architecture with a central processor executing a loop of fetching and changing discrete buckets
of data stored in the memory,
6
Lucid uses the paradigm according to which data is in a constant flow
moving through the network of processors or arcs.
7
The Lucid program is merely a math expression, and
its output is its result after evaluation.
As for the fact that Lucid is a definitional programming language, it follows from this that there
should be no side effects in any statement used, as well as there cannot be any history sensitive variables
at all.
8
A programmable statement in Lucid is merely an assertion concerning a connection of two
8
Sally C. Johnson, “A Strategy for Automatically Generating Programs in the Lucid Programming Language” p.2-3
7
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 8
6
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 6-7
5
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p.viii
4
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language.” p.viii
3
Sally C. Johnson, “A Strategy for Automatically Generating Programs in the Lucid Programming Language’
NASA Technical Memorandum 89094” (Hampton, VA: Langley Research Center, June 1987), p.2
3
continuous streams of data.
9
As such, a variable declared as 2 in Lucid does not indicate its value but an
infinite flow of 2s.
10
It is in such a manner that the programmer can construct self-contained filters
operating infinitely on a stream of data until obtaining the desired result.
Technical Features
The understanding of Lucid programming language requires knowledge of its peculiarities of
syntax, in particular sequence progress and sequence control operators. This programming language uses
temporal operators to efficiently handle iterations as mathematically defined sequences rather than manual
loops. In particular, the first operator identifies the value of the beginning of the continuous stream, while
the next operator defines the next value in the following run-time step.
11
As far as sequence operations are
concerned, Lucid programming language learners use the fby operator meaning 'followed by'. When a
certain variable uses fby, this operator shifts its left operand's first value forward in front of the right
operand's sequence.
12
Moreover, sequence control in terms of loop simulation takes place with the help of
the asa operator meaning 'as soon as'. This operator stops advancing a stream and captures the exact value
of a variable at the very time when a given boolean condition becomes true.
13
Infinite stream structure handling in the Lucid programming language brings certain difficulties in
run-time evaluation, but those can be overcome with the use of a demand-driven sequence control
mechanism. Any procedure implementing an infinite data stream in the language will result in machine
crash because of infinite memory allocation or infinite looping. Therefore, the problem may be solved
with the help of lazy evaluation in Lucid programming language. While parameters are not evaluated
automatically, their demand-driven evaluation depends on the required sub-expression that is being traced
backward starting from the final output, “like an infection”.
14
Thus, thanks to semantic cache, the
14
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 37
13
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 70-71
12
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 46, 177
11
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 46, 177
10
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 4
9
Sally C. Johnson, “A Strategy for Automatically Generating Programs in the Lucid Programming Language”p. 2
4
interpreter has an opportunity to leave any unnecessary computational branch of a program in terms of
determining its final output.
15
This programming environment which executes the algorithm serves as the physical connection
between the mathematical theory and its functionality. In past times, this was achieved by means of the
pLucid compiler which ran on the UNIX platform. Since the UNIX shell allows for the notion of piped
filters using streams of characters, the dataflow mechanism adopted in pLucid seemed natural to any
command line operator.
16
The pLucid evaluator was actually an interactive process on UNIX which made
demand driven requests for input through the keyboard stream and produced corresponding output on the
screen.
17
By applying special filter functions, pLucid programmers could actually pipe their infinite
streams to normal UNIX utility applications, thus mixing pure mathematics with operational commands.
18
In addition to that, it is also important to learn about data types in the Lucid programming
language. Surprisingly, the language is fundamentally typeless, meaning it lacks strict compile-time type
declarations and checking.
19
Nevertheless, when implemented using pLucid, a number of primitive data
types are used such as integers, reals, words, strings, and finite lists based on the POP-2 language.
20
To
avoid terminating the execution of dataflow, the program uses unique objects called `error` and `eod` (end
of data).
21
Evaluation
When considering where exactly Lucid fits into the context of overall programming techniques,
one cannot fail to acknowledge its great structural benefits in parallelism while taking into account the
factors that caused its limited usage in practice. Mathematically, Lucid can be seen as a masterpiece as it
21
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 194
20
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 185
19
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 147, 185
18
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 106
17
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 201
16
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 171
15
E. A. Ashcroft and W. W. Wadge, “The Syntax and Semantics of Lucid - Technical Report CS-84-24” (Ontario,
Canada: Department of Computer Science, University of Waterloo, August 1984), p. 13
5
avoids the problem of race condition, deadlock, and aliasing which arise in concurrent computation using
Java or C. Since there are no implicit actions involved, it becomes easy for a compiler to distribute a
program written in Lucid over a thousand nodes in parallel computing systems. Unfortunately, however,
the paradigm was too unconventional to catch on. Most enterprise software developers had already been
well versed in the von Neumann machine and wanted low-level programming capabilities that allow
explicit control over memory and execution order.
22
In addition, simulating an idea such as the infinite
sequence network on a system that was not originally designed to do so resulted in a lot of execution
overhead.
23
Even though the theory behind Lucid was brilliant when applied to hardware models, signal
processing applications, and parallel mathematics, the cost of execution was simply too high.
Conclusion
Learning about the Lucid programming language meets all of the aims of this work since it is a
clear example of implementing the dataflow model. Making a programmer avoid anything like mutable
state, global variables, and loops in order to demonstrate that any problem might be described as a simple
mathematical formula for the relationships between infinite streams of data, the language managed to
prove that declarative programming may function beyond the limitations created by the von Neumann
architecture. While it was imperative languages that ended up dominating the commercial software market
due to their correspondence to the hardware level, the purely declarative approach of Lucid uniquely
demonstrated a way it can be done.
23
E. A. Ashcroft and W. W. Wadge, “The Syntax and Semantics of Lucid - Technical Report CS-84-24” p. 12-14
22
William W. Wadge and Edward A. Ashcroft, “Lucid, the Dataflow Programming Language” p. 9
6
Appendix: Sample Code
In order to showcase the operational efficiency of Lucid sequential operations compared to the
conventional iteration loop in Java, the below logic tested code calculates a moving average of random
numbers, as suggested by Wadge and Ashcroft. Rather than employing a counter for each repetition, the
below mentioned program generates two streams, s and n. The stream s consists of partial sums computed
through fby, while the stream n is just the number of inputs counted sequentially.
Code snippet:
next s/n
where
s = 0 fby s + x;
n = 0 fby n + 1;
end
Newton's Square Root Approximation:
The following code is an algorithm that finds the square root of incoming values in streams using
nesting. This shows the usage of the conditional statement known as asa to exit the inner computation if
the difference is sufficiently low, and is current for keeping the value of the outer x unchanged in the inner
loops.
Code snippet:
approx asa count eq 10
where
X is current x;
approx = 1 fby (approx + X / approx) / 2;
count = 1 fby count + 1;
end
7
Bibliography
1. Ashcroft, E. A., and W. W. Wadge. “The Syntax and Semantics of Lucid - Technical Report
CS-84-24.” Ontario, Canada: Department of Computer Science, University of Waterloo, August 1984.
Available:
https://cs.uwaterloo.ca/research/tr/1984/CS-84-24.pdf
2. C. Johnson, Sally. “A Strategy for Automatically Generating Programs in the Lucid Programming
Language’- NASA Technical Memorandum 89094.” Hampton, VA: Langley Research Center.
June 1987. Available:
https://ntrs.nasa.gov/api/citations/19870012992/downloads/19870012992.pdf.
3. W. Wadge, William, and Edward A. Ashcroft. “Lucid, the Dataflow Programming Language 1.”
London, UK: Academic Press. 1985. Available:
https://worrydream.com/refs/Wadge_1995_-_Lucid,_the_Dataflow_Programming_Language.pdf.