March 95 - A First Look at Dylan: Classes, Functions, and Modules
A First Look at Dylan: Classes, Functions, and
Modules
Steve Strassmann
Dylan is a new object-oriented dynamic language (OODL) that's attracting a lot of
attention. Like C++, it's designed for efficient compilation and delivery of mainstream
commercial applications. However, Dylan differs from C++ in important ways that
make it more powerful and flexible. Here we'll focus on one important difference from
C++: the way classes and their methods are organized.
The organization of classes and functions is different in Dylan than in C++. In C++,
classes are used in two ways: to encapsulate data and as a scoping mechanism. Methods
in C++ "belong to" classes, and there are many complex mechanisms governing access
to methods from "inside" and "outside" a class. In Dylan, classes are used only for data
encapsulation -- there's no notion of methods being owned by classes. As a result,
specifying and using methods is cleaner, simpler, and more expressive.
Access is simplified and abstracted through modules, which are a way of grouping
related classes, methods, and variables. Rather than being tied to a single class, each
method belongs to a family called a generic function. Eachgeneric function can operate
on one or more related classes, and can be extended across one or more modules. We'll
talk more about generic functions, polymorphism, and modules later in this article.
Dylan has many other features that distinguish it from C++, including:
• automatic memory management
• clean, consistent syntax
• fully and consistently object-oriented model
• dynamic as well as static type checking
• support for incremental compilation
• first-class functions and classes
There's not enough space here to do justice to each of these topics, so we'll just touch
on some of them as we discuss classes, functions, and modules. As you might expect,
this article assumes you have some familiarity with basic object-oriented concepts,
such as classes, instances, and inheritance.
On this issue's CD, you'll find a freeware Dylan interpreter, called Marlais, that you
can use to execute code written in Dylan. Simply run the application and enter your
code at the prompt. Also on the CD are the code samples you'll see in this article, plus
the Dylan Interim Reference Manual and other Dylan goodies.
Apple's implementation of Dylan, called Apple Dylan, is planned to ship later this year.
One great feature of Apple Dylan is that it allows you to call existing C and
C-compatible code libraries, such as the Macintosh Toolbox. See "Creole: Using the
Toolbox and Other C Code From Within Dylan Code" for details.
______________________________
CREOLE: USING THE TOOLBOX AND OTHER C CODE FROM
WITHIN DYLAN CODE
With any new language, you're bound to wonder whether you'll be able to get at
the "really good stuff." You know, interfaces always seem to be published just
for C programmers, and nobody else. I don't mean merely the Macintosh
Toolbox, but any other code already written by you or a third party, like
database access routines or advanced graphics libraries. In many cases (such
as with the Macintosh Toolbox), you may not have access to the source code, so
recompiling or translating it into the new language is simply not an option.
Apple has designed a cross-language extension to the Dylan language. This
extension, called Creole in Apple Dylan, allows you to build programs with
parts written in both Dylan and C or C-compatible languages. We at Apple hope
the extension will be supported by other Dylan implementations, but since the
extension isn't part of the standard Dylan language, it's not required. (The
Marlais interpreter on this issue's CD doesn't support it.) In the future, Apple
will also support the System Object Model (SOM) extension, which is used by
OpenDoc. Here we'll take a look at some features of Apple Dylan's Creole
implementation.
Once you import C interfaces into Dylan, you can call C functions and refer to
C structsas if they were Dylan functions and objects. There's no need to translate the C headers first; Creole reads them directly. In the following
simple example, we import the interface file OSUtils.h, which contains the
Toolbox function SysBeep; we can then, for instance, callSysBeep(1) from
Dylan.
define interface
#include "OSUtils.h",
import: {"SysBeep"};
end interface;
Creole provides these additional facilities:
• An access path (linking) mechanism links compiled C-compatible
modules, including C++, Pascal, assembler, and FORTRAN modules, into a
Dylan application. Creole supports object (".o") files, shared libraries (Apple
Shared Library Manager or Code Fragment Manager), inline traps, code
resources, and PowerPC transition vectors.
• Cross-language calls allow Dylan routines to call routines in another
language, and vice versa.
• Name mapping translates names of entities in another language into Dylan
variable names in a specified module. Apple Dylan offers several convenient
mappings for common naming conventions.
• Type mapping translates C types into Dylan types and provides type
checking for Dylan clients of the Macintosh Toolbox and other interfaces.
• Low-level facilities provide Dylan programs with direct use of machine
pointers and the raw bits pointed to by the machine pointers.
A define interface statement imports one or mointerface files and creates Dylan classes, constants, and functions corresponding to the C types,
constants, and functions in the interface files. Like any Dylan expression, a
define interface statement exists in a particular module, as do the
variables that it defines. You can export and rename these variables using
module options just as you would for normal Dylan variables (as discussed
later under "The Role of Modules").
Many options are available to override Creole's default behavior. For example,
you can do any of the following:
• selectively import parts of an interface
• explicitly control type mapping -- for example, to map StringPtrto • explicitly control name mapping to avoid name conflicts because of the
difference in case-sensitivity and scoping rules in Dylan and C
• work around undesirable features in the interface or in Creole
• control tradeoffs between runtime memory consumption and dynamic
functionality
CLASSES AND OBJECTS
Dylan is fully and consistently object-oriented, much like Smalltalk(TM). Everything
is an object, including numbers, strings, and even functions and classes themselves.
Each object descends from a single common ancestor class, named .
The <> characters are not some fancy operator but are merely a
typographic convention for indicating the name of a class in Dylan, just as
all-uppercase letters might indicate a macro in C++. You're allowed to name a
class without the <> characters, but that would be considered bad style.*
To illustrate how classes are used in Dylan, let's look at one of our samples, SimMogul,
to model Hollywood high finance. In Listing 1, we define a few classes, creating the
inheritance hierarchy shown in Figure 1.
Listing 1. SimMogul -- basic version
slot script; // All you need is a hot script
slot star; // and a big name.
end class ; // Last two words are optional. slot name; // Actor's name
slot salary; // Cost to hire
slot fans; // Audience size
end class;
define class