Chapter 1:
Introduction
Intended Audience
This manual serves dual purposes. First and foremost, it is intended as
a quick reference guide to the Daisy language. Although the excellent
and thorough (although slightly dated) Daisy Programmer's Manual exists,
it is more of a comprehensive reference and tutorial than a concise
description. It is our hope that this thin manual can more readily track
the changes to this dynamic and evolving language.
Second, we have attempted to provide a simple and unassuming
introduction for intermediate-level programmers weaned on conventional
imperative programming languages. Although hardly a substitute for a
good introductory text on functional programming, we attempt to
highlight the key differences between Daisy and more traditional
languages, and in some cases explain the rationale behind the language
design. We realize that this approach may irritate more knowledgeable
readers; we ask that you bear with us and skim material that seems
overly pedantic.
In this manual there should be enough information for you to get a sense
of what Daisy is like and to be able to write some simple programs. We
assume that you have some experience as a programmer in another
programming language and understand basic programming concepts. We do
not assume extensive programming experience or a lot of familiarity with
high-level languages or language implementation.
This manual does not provide examples of significant programs written in
Daisy. For that we refer you to our companion volume Daisy Programming
or the aforementioned Daisy Programmer's Manual.
Organization of this Manual
- Chapter 2 (Syntax, Data Types and Evaluation) is an overall introduction
to the basic structure and form of the language. If you read only one
chapter, this should be it, as it explains the important things you need
to know.
- Chapter 3 (Special Forms) describes the language constructs used to
create local variables and control evaluation in special ways, such as
conditionals and sequencing. Some simple programs are introduced.
- Chapter 4 (Basic Primitives) describes the basic primitives that Daisy
provides. After reading chapters 2 and 3 and skimming 4 you should be
able to write some simple programs.
- Chapter 5 (Streams and Higher-Order Primitives) outlines the concept of
higher-order functions, how they are used in Daisy and introduces some
of the important primitives that use them. The important topics of
mapping primitives and streams are introduced here.
- Chapter 6 (I/O Primitives) explains Daisy's stream I/O model and
facilities for keyboard, terminal, file, and network I/O. We conclude
with a discussion of Daisy's interface to external (host OS) processes.
- Chapter 7 (Advanced Primitives) describes all the rest of the Daisy
primitives that don't fall into the earlier categories.
What is "Daisy"?
Daisy is a computer programming language with some interesting
properties. Some of the adjectives that have been used (perhaps not
altogether accurately) to describe it include: high-level, symbolic,
list-processing, concurrent, functional and demand-driven.
- Daisy's "high-level" classification results from a number of features
which Daisy shares with other high level languages like Lisp, Scheme,
BASIC, Perl, Tcl and Smalltalk. First, the basic constructs in the
language tend to be more powerful yet less verbose than in conventional
languages, and can be combined in more flexible ways. Second, Daisy
includes built-in, automatic memory, process and device management
systems. This combination leads to programs that are much shorter and
more readable than in traditional programming languages, because they
don't have to include a lot of code for allocating and managing system
resources.
- Daisy is a symbolic, list processing language. Its primitive data
types are numbers, symbols (string-like objects) and lists. These three
primitive types, combined with a general object system for building more
compound types are sufficient to handle the vast majority of programming
tasks one is likely to encounter.
- Daisy is a concurrent, demand-driven, functional language. In Daisy
you write programs that are compositions of functions, objects and data
structures rather than statements that imply an ordered series of
operations. Programs become more a specification of what than when. This
gives the system a lot of flexibility in deciding the time and order of
computing the results. Some computations might be delayed indefinitely
if they are never used; others might be computed speculatively (i.e. on
the chance that they might be used) or in parallel.
- Daisy has latent typing (aka dynamic typing). This means that it is
values and objects that have types associated with them and not
variables. With latent types a variable can hold any value (since
variables have no type). However, the system does expect specific value
types for many kinds of operations, and errors will occur if the correct
types of values are not supplied as arguments.
History of Daisy
The Daisy language is the culmination of a number of research projects
relating to Lisp-family languages over a twenty year period from the mid
1970's to mid 1990s at Indiana University.
Conventions Used in this Manual
We use the following typographic conventions in this manual:
- Language keywords, syntactic punctuation and program fragments or
listings are generally shown in Courier font.
- Items in Courier italics indicate that expressions of a given type are
expected in this position. The letter or word in italics indicates the
data type the expression should evaluate to and a subscript (if any) is
a notational aid in understanding the purpose of the expression in the
surrounding context (see example below).
- Boldface may be used for emphasis, but does not have special
meaning.
- ellipses (
...
) indicate extra items may follow,
possibly/likely having a similar type signature to the preceding item(s).
- A right arrow (
=>
) means "evaluates to".
Here is an example:
if:[ Epred Ethen Eelse ] => Ethen if Epred is true, Eelse otherwise
This says that in the conditional construct, the if
keyword, the colon and the brackets are required syntax, while inside
the brackets, three arguments are expected: a boolean predicate
expression, a general then expression and a general else expression. The
entire expression evaluates to the value of the then or else expression,
depending on the value of the predicate expression. In C syntax this
expression would be:
( Bpred ? Ethen : Eelse )
Here is a concise listing of italic expression placeholder types. Some
of these are self-explanatory, others are described elsewhere in the
manual.
Placeholder Expression
E valid value
N number
F function
M string, erron (message)
I literal, symbol (identifier)
L list
S stream
C character
B boolean
D unsigned constant (directive)
V value of the corresponding expression to the left of the arrow
Concepts and Terminology
An environment is the set of local variables and their values. In
conventional languages the environment is maintained as a sequence of
stack frames containing function parameters and locally declared
variables. One can read and set those variables directly, but it is
usually not possible to manipulate the environment itself as a malleable
data structure. Instead, it is manipulated implicitly; it gets extended
when you call a function or declare some local variables, and shrinks
when the execution path returns you out of that local scope. The main
reason for this is to prevent corruption of the environment structure
(stack) which would wreak havoc with the underlying system, since it
contains other critical items like return addresses. In Daisy the
environment is maintained separate from the stack so corrupting the
stack is not an issue. This makes it possible for the programmer to
manipulate the environment.
In conventional languages like C, all functions are defined at top level
at compile time. They might be global or defined in classes, packages or
modules. In the body of the function, variable references can refer to
function parameters, local variables or top level variables (global or
class/package/module). In Daisy, functions can be nested. A variable
reference can refer to any variable in the environment.