[Prev][Next][Index][Thread]
Re: A Dylan FAQ
OK, here's some more, with what people already posted worked in.
The only one I can't remember is about before-method and after-method,
which Dylan can't do anyway. :-)
- Rob.
----
Dylan FAQs.
1. Background.
What is Dylan?
Dylan is a general-purpose high-level programming language.
Who created Dylan?
TODO
What implementations are currently available?
There are two major implementations available.
Functional Developer is a commercial Dylan implementation sold by
Functional Objects, Inc. (http://www.functional-objects.com) It is
currently available for Windows, and features a very sophisticated IDE
and a high-performance native-code compiler.
Gwydion Dylan (http://www.gwydiondylan.org) is an open-source
implementation that is mostly aimed at Unix-like systems (including
Mac OS X and Cygwin). It is, like most Unix compilers, a command line
app, and it compiles using C as an intermediate form.
Is it available on my platform?
Probably. See above.
Is there a standard?
There is no ISO or ANSI Dylan standard, but "The Dylan Reference
Manual" written by Andrew Shalit (ISBN 0-201-44211-6) exists, and
incompatibilities with it are usually treated as bugs. Also, both
major implementations work to make sure that their libraries are
intercompatible.
Is there a reference implementation?
Not in the sense of Perl or Python, no.
What does the name "Dylan" mean?
It's a portmanteau word, from the phrase "DYnamic LANguage."
So was it taken from Bob Dylan or Dylan Thomas?
Despite lawsuits to the contrary, neither.
Wasn't Dylan used for programming Newtons?
No. It was considered for this purpose, but was not ready in time.
Newtons were programmed using NewtonScript, a prototype-based language
similar to SELF.
2. Ancestry.
Is Dylan a form of Lisp?
Yes, to the same extent that Scheme is a Lisp. You can think of Dylan as
the offspring of Scheme and CLOS, and you won't be too far wrong. Some
Lispers don't even think Scheme is a Lisp, though.
Syntactically, Dylan shares a few features with CLOS, but otherwise it
has an infix-style syntax like Pascal, C or Java.
What happened to the Lisp syntax?
It was replaced by the current infix syntax, presumably to appeal to a
more mainstream programming audience.
Where can I find a copy of the Lisp syntax?
You can still find DEC WRL's "Thomas" implementation of Lisp-syntax
Dylan on the net, including a version embedded into Gambit Scheme.
Old copies of the preliminary Dylan Reference Manual from 1992 are still
available on the Web. These use the prefix syntax, but are incomplete.
Why don't you re-implement the List syntax?
The prefix and infix syntaxes are mutually incompatible. In particular,
there is no way to automatically convert macros between the two
languages.
Is Dylan a superset of Java?
No. This misconception probably came from a badly worded press-release
for the Dylan Reference Manual.
3. Gotchas and Good Practice.
Why do I have to leave spaces between every single token?
Because Dylan has a very rich syntax for identifiers. The graphical
ASCII characters, like '?', '!' and '-', are all legal as parts of Dylan
identifiers, and this means that you need to put spaces to distinguish
'twelfth-elephant' from 'twelfth - elephant'.
Why should I use a naming scheme?
(with-, do-, my-, the-)
TODO
Why should I avoid calling functions "element" or ...?
TODO Identify all operator function names in Dylan.
Dylan is lexically scoped, and methods are simply functions bound to
names. If you name a variable "element", then you will shadow all
references to the module-level "element" within the lexical scope of
the block. Since the "foo[bar]" notation for element access is just
syntactic sugare for "element(foo, bar)"
In other words
begin
let v = #[1, 2, 3, 4, 5];
let elt = 'x';
v[4];
end;
will yield '5', the last element of v.
But doing
begin
let v = #[1, 2, 3, 4, 5];
let element = 'x';
v[4];
end;
will yield an error. This is because "let element = 'x';" rebinds the
element() method to the character 'x', and this means that you will
try to call the character 'x' as a function in the last line. Not
happy. Likewise, this is also true for object slots, names in the
Dylan module and top-level functions.
What do =, =, := and == mean and what are the wrong ways to use them?
\= and \== are the two equality methods in Dylan. \== is the object
identity method; it return #t if the two objects it compares are the
same object. You can think of this informally as asking if the two
variables being compared point to the same hunk of memory. This is
akin to the 'eq?' function in Scheme, or the Python 'is' operator.
\= is the semantic equality predicate. It should return #t if the two
objects *mean* the same thing. It's like "equal?" in Scheme. \= is
predefined for the built-in classes, but it's extensible to cover the
classes you define.
As a rule of thumb, you probably want to use \= unless you
deliberately want to test for object identity.
':=' is the syntax used to spell assignement in Dylan. There's a bit
of syntatic sugar in the ":=" macro. If you are assigning to a
binding, then the usual imperative update of the variable happens.
When assigning to collections or to slots, the := syntax expands
into a setter method. That is,
v[x] := 4;
object.slot := 7;
is equivalent to
element(v, x) := 4;
slot(object) := 7;
is equivalent to
element-setter(4, v, x);
slot-setter(7, object);
When you write a -setter method of your own, you should take care that
it *always* return the value that the object was set to. People sometimes
write code like this:
foo.bar := baz.quux := thingy;
and use assignment as an expression. If you don't return the set
value, you lay the groundwork for some dramatically perverse bugs.
TODO = as let binding operator.
What does object.slot() mean?
Let's do this step by step. The "." syntax is just sugar for a
function call -- "foo.bar" is the same thing as "bar(foo)". So
"object.slot()" is just the same as "slot(object)()".
In other words, we are calling the 'slot' method of 'object', and then
calling it as a nullary function. (Remember that functions are first-
class in Dylan, and can be stored in objects and variables just like
any other data.)
How do I initialize a slot?
Usually, you use a slot-specification in the define-class statement.
Here are some examples:
define class <foo> (<object>)
slot bar,
required-init-keyword: bar:;
end class;
This means that there will be a keyword argument "bar:" in the
make(<foo>) call, and that an error will be signalled if it's not
present.
define class <foo> (<object>)
slot bar,
init-keyword: bar:,
init-value: 42;
end class;
This means that you may call with a keyword argument like
"make(<foo>, bar: 14)", but that if the keyword bar: is absent
the slot will default to 42.
define class <foo> (<object>)
slot bar,
init-function: method() seconds-since("15 Jan 2001") end,
end class;
An init-function slot specification means to call the zero-argument
function to get the value to initialize the slot with. You can mix and
match init-keyword, and init-value/init-function arguments and they
will generally have the obvious effects.
You should try to supply initializers whenever possible; this makes it
possible for the compiler to prove that the slot is never unbound, and
lets it generate slightly faster code (since it doesn't have to
generate tests to see if the slot is unbound at each access).
What is initialize()?
TODO
What are unsupplied() and false-or()?
unsupplied: TODO
false-or() is a function that creates a new type from an old one.
(Everything is an object in Dylan, including classes and types.)
Specifically, false-or(<foo>) returns a new type that returns #t for
exactly all the values that instance?(x, <foo>) returned #t for, plus
the value #f is also an instance of false-or(<foo>).
This is useful when you want to add an out-of-band value to a type.
What is sealing?
TODO
What are libraries and modules for? How are they different?
TODO
Macros? Aren't macros bad?
TODO
What is the "FFI"?
- Oh, okay. Why don't you just use SWIG, though?
TODO
Why should I put \ in front of macro and operator exports?
TODO
Why should I put \ in front of operators when I pass them to a function?
TODO
When should I put # in front of something?
TODO
Why is this broken: #( fun1(), fun2(), fun3()?
TODO
What's the difference between "Hello" and #"Hello" ?
TODO
What's the difference between #"Hello" and Hello: ?
TODO
So why should I use the former for symbols and the latter for keywords?
TODO
How do I exit a (deep) loop like in C++ or Java?
TODO
What names does Dylan define behind-the-scenes?
TODO
What are -getter and -setter methods?
TODO
How do I export a slot form a module?
TODO
How do I write a finalizer for an Object?
TODO
4 Language Design.
What are keyword parameters?
Most functions distinguish there arguments by position. Keyword
arguments let you identify arguments by their name. Eg, the
call
range(from: 0, to: 10)
returns a sequence of integers from 0 to 10, inclusive. This
would be declared in Dylan with something like:
define method range(#key from :: <integer>, to :: <integer>)
=> (s :: <range>)
// implementation
end method;
What are they good for?
"If you have a procedure with ten parameters, you probably missed
some." -- Alan Perlis
Whenever you have functions with a lot of parameters, it's *very*
convenient to be able to simply name them. This comes up a lot in GUI
programming in particular.
TODO optional parameters and default values for keywords.
What is a generic function?
A generic function is a special kind of function that contains a
collection of methods. When it is called, it does no work other than
selecting a method based on the types of the arguments, and then it
passes the arguments on to the method it selects. Think of it as a
kind of C++ like virtual function that a) doesn't have to live inside
a class, b) is a first-class function, and c) can dispatch dynamically
on more than one argument.
Where can I read up more on generic function implementation?
The Cecil project at the University of Washington has a ton of papers
describing how to optimize multimethods and other OO features.
http://www.cs.washington.edu/research/projects/cecil/www/Papers/papers.html
Of particular note for multimethods is
"Efficient Multiple and Predicate Dispatching"
http://www.cs.washington.edu/research/projects/cecil/www/
Papers/dispatching.html
Johnathan Bachrach implemented the algorithms described in this paper,
and reports a good performance enhancement in the Fun-O compiler.
Dujardin and Amiel's paper "Fast algorithms for compressed multi-dispatch
tables generation" describes another appraoch. To my knowledge this has
not yet been implemented in a Dylan compiler, but Eric Kidd is currently
investigating it for his thesis.
Also of interest is "Optimization of Object-Oriented Programs Using
Static Class Hierarchy Analysis" (This shows how compilers can use
Dylan's sealing directives.)
http://www.cs.washington.edu/research/projects/cecil/www/Papers/hierarchy.
html
What GF dispatch algorithm does Dylan use?
It depends on the compiler.
Gwydion Dylan first tries to eliminate GF dispatch altogether using
compile time analysis of the types of the arguments. If it can't do
that, but can narrow it down to a set of methods known at
compile-time, it will often generate a function that does dispatch as
a set of nested if-statements. If it can't do that, it uses a slow,
fully general dispatch algorithm, but caches the types of the last
call. There is also a seperate path for one-argument GFs, which can be
optimized somewhat more efficiently.
Why don't objects own methods?
Because using generic functions makes multimethods very natural to use
and provides an elegant solution to the binary method problem.
Consider numbers, and the addition operation on them. We would expect
an OO language to do the natural conversions between (say) integers
and floating point. In a singly-dispatching language, each addition
method would have to know about all of the other classes that it can
receive as an argument. When you add (for example) bignums to the mix,
every addition method of every class needs to be updated. This is
very messy.
In Dylan, you would only need to add exactly the methods to add
bignums, and you wouldn't need to touch the other definitions.
Generic functions also makes the Visitor pattern utterly transparent,
and consequently make the Interpreter pattern trivial to implement.
TODO [example goes here]
What is common-dylan?
Common-dylan is the set of libraries and extensions that both Gwydion
and Fun-O have agreed to support. This includes things like the stream
interface, the threading model (though GD doesn't do threads yet), and
so on.
Why does it take three files to compile "hello world"?
TODO
What are first-class types and functions?
TODO
What is Syntactic Sugar?
TODO
5. Language Comparison.
Does Dylan have a MOP?
Some introspection on classes and generic functions is possible, but a
full Meta-Object protocol was deemed too big a performance hit.
Can Dylan load arbitrary libraries and methods like Java can?
There's no standard way of doing this. Functional Developer can do it
with LoadLibrary. Note that a lot of what Java uses class loading for
can be replaced with Dylan's first-class types and functions.
How do I get Java/C++-style access control in Dylan?
Modules in Dylan are used to control access. A common idiom in
Dylan is to see module declarations like this:
define module foo-internals
use dylan;
export foo, foo-setter, bar, baz, quux, <tharp>;
end module;
define module foo
use dylan;
use foo-internals,
export: {<tharp>, baz, quux}
end module;
Can I use Dylan for DB/Graphics/Network/XML/etc?
Probably. Ask on comp.lang.dylan.
Is Dylan a Functional Language or an OO Language?
Yes. :)
Dylan has first-class functions, proper lexical scoping, and is
usually tail-recursive: that's from the functional universe. It also
has multimethods, inheritance, and "objects all the way down": that's
from the OO universe.
The combination is very powerful and a lot of fun to program in.
Does Dylan produce native executables?
Both Functional Developer and Gwydion Dylan produce native executables.
Is Dylan Garbage Collected?
Yes.
Can Dylan talk to C/C++/Objective-C/Java?
Yes. See "What is the C-FFI"
Can Dylan Use COM/CORBA/ActiveX/DLLs?
Functional Developer can. Gwydion Dylan can't yet.
6. Resources.
What tools are available for working with Dylan?
- Editors, emacs modes, etc.
- Compilers, debuggers, profilers
- Class browsers
- UML tools that generate/read Dylan
- etc.
Where can I find Dylan code on the Internet?
http://www.gwydiondylan.org/
ftp://berlin.ccc.de/pub/gd/contibuted/
http://www.double.co.nz/dylan/
Where can I find Dylan tutorials on the Internet?
http://www.gwydiondylan.org/
(That Develop Article)
Where can I find Dylan white papers / overviews on the Internet?
http://www.functionalobjects.com/
http://www.gwydiondylan.org/
What books on Dylan are available?
The Dylan Reference Manual ("The DRM")
Authors
ISBN 0-201-44211-6
Adison-Wesley 1996
Notes
Dylan Programming("The Harlequin Book")
Authors
ISBN Publisher Date
Notes
Programming in Dylan
Iain D. Craig
ISBN 3-540-76053-9
Springer-Verlag 1997
Written using the Provisional DRM for reference and avoiding the
use of more complex collection types. Contains an extended program
example, many code samples, and a thorough introduction to the basics of
Dylan. Generally considered the weakest of the three.
Dylan is a Trademark of Apple Computer, Inc. Functional Objects and
Functional Developer are trademarks of Functional Objects.
Questions Submitted by: brk@jenkon.com, Rob Myers
Answers Submitted by: Bruce Hoult, Chris Double, Neelakantan
Krishnaswami, Rob Myers