|
|
Home
>
1. overview
>
1.1 'what is' about Dylan
|
Previous
Next
|
|
|
|
|
|
|
|
|
|
|
|
Albert Wagner
|
Would someone please post a short definition of imperative,
functional and OOP languages.
I thought I knew OOP from Smalltalk until I read of Dylan's
approach.
|
|
Neel
(Neelakantan
Krishnaswami)
and
Joseph N.
Wilson
|
Imperative programming:
a programming style that uses explicit
- mutable state (mutable variables)
and
- control flow (goto, for-loops, branches,
etc.).
Conceptually, you perform a computation by changing the state of
the computer.
A procedural language adds functions and procedures on top of this
foundation, and then you get C and Pascal.
For example, here's an imperative function to find the factorial
of an
integer:
define function factorial
(n :: <integer>)
=> (n! :: <integer>)
let n! :: <integer>= 1;
while (n >0)
n! := n! * n;
n := n - 1;
end while;
//
n! // return n!
end function factorial;
Functional programming
A programming style that emphasizes an "equational" approach
is
taken:
- instead of changing the state of
a machine, a program is defined
as the solution to a set of functions.
- in order for mathematical laws to
hold, in particular that
a = b => f(a) == f(b)
- mutable state and explicit control
flow are avoided.
(For example, if there were mutable global variables referenced
in f, then there would be no guarantee that one call to f(3) would
have the same value as another call f(3).)
The usual definitions of functional programming are also that
- functions should be first-class.
In other words that they can be passed as arguments and created
and returned as values. (Both Smalltalk's blocks and Dylan's
methods are first-class functions.)
For example, you might define factorial as:
define function factorial
(n :: <integer>)
=> (n! :: <integer>)
if (n = 0)
1
else
n * factorial(n - 1)
end if;
end function factorial;
taking the definition of factorial straight from the mathematical
definition.
Object-oriented Programming (OOP)
A style of programming that emphasizes two concepts.
- First, the idea of subtyping:
--- values can belong to more than one type.
- Second the idea of dynamic
dispatch
--- a method is selected based on the most specific type of the
arguments.
For example, here's an OO factorial:
define constant <zero> = singleton(0);
// The type <zero> contains only the
// int 0, so <zero> subtypes <integer>.
define method factorial (n :: <zero>)
=> (n! :: <integer>)
// in case of type <zero> return
1
end method factorial;
define method factorial (n :: <integer>)
=> (n! :: <integer>)
// in case of type <integer>
which excludes
// the zero return
n * factorial(n - 1)
end method factorial;
We still haven’t handled all the cases of possible argument values. If
the argument is a negative, factorial has been asked to do an
impossible job. We can create a type that consists of a limited
range of integer values and use that to provide a behavior for the
rest of the cases
define method factorial (
n:: limited(<integer>, max: -1))
error ( facorial: Bad argument,
n )
end method factorial
Note that the factorial method chosen for an argument depends on
the value passed to the function factorial.
The way that Dylan's OO is different from Smalltalk is the way
of selcting a method
- In
Smalltalk selecting the method based only on the first
receiver (message-passing OO),
- Dylan selects a method based on *all*
of the arguments
(multimethod dispatch OO).
We need two or more arguments to demonstrate multimethods,
and this post has gotten long enough, so I'll leave that for
another day.
|
|
Joseph N.
Wilson
|
More on generic functions:
We can create an argument whose type is the single value 0. (Such
a type can be created by evaluating the expression singleton
(value)).
- as described above via
define constant <zero> = singleton(0);
// The type <zero> contains only the
// int 0, so <zero> subtypes <integer>.
define method factorial (n :: <zero>)
- or via
define method factorial (n == 0)
That's possible, because
x == $special-x
is a shortcut for
x :: singleton($special-x).
Why is the right method used if we evaluate factorial (1), factorial
(0), or factorial (-1)?
- Which type do you believe is more
specific to the object 0,
the singleton type that contains only the value 0 or the
class <integer>?
- Which type do you believe is more
specific to the object -1,
the range of integers containing only negative integers or
the class <integer>?
|
|
|
|
|
|
|
Philip Wadler
in ACM SIGPLAN Notices
(33) 25-33 , February 1998
|
The functional community splits in two camps. Lazy ,languages evaluate arguments
on demand and so require a highly disciplined use of side effects; strict languages
evaluate arguments eagerly, but make it easier to exploit side effects.[ ..]
Most functional lanuages now provide some means of interworking with C or other
imperative lanuages. [...]
Functional programmers often proclaim that the use of high-order functions promotes
reuse. The classical examples are the map and folder functions, which
encapsulate common forms of list traversal, and just need to be instantiated with an
action to perform for each element. Most, but not quite all, list processing can be
easily expressed in terms of these functions.
[ The experience with the strict functional language Erlang] suggests this notion
of
reuse scales up to support the current client-server architectures. A set of libraries
encapsulate the common server requirements, and just need to be instantiated with
an action to perform for each request. Most, but not quite all, servers can be easily
expressed in terms of these libraries.
|
|
Hans-Martin Adorf
|
The usefulness of a programming language is generally greatly enhanced if it is
``functional'' (as opposed to imperative). A functional language (Hudak 1989) is,
broadly speaking, a language ``that emphasises the evaluation of expressions, rather
than the execution of commands. The expressions in these languages are formed by
using functions to combine the basic [data] values'' (Jones 1994). Functional
languages support and encourage programming in a functional style. They are usually
very expressive and often allow a direct translation of algorithms in mathematical
notation into executable code.
|
|
|
|
Doug Hockin
|
|
|
Scott McKay
|
Well, it works for *me*. ;-)
A lot of my Dylan code is written in a purely functional style.
Dylan does not preclude doing this, and in fact, it is easy to do so.
However, purists could rightfully point out that Dylan does not *require* a
functional style. Me, I think it should be on the list, but I'm not a purist...
|
|
Bruce Hoult
|
If Common Lisp and Scheme and OCaml are there (which they are) then
Dylan certainly should be too.
Like them Dylan has all the features needed to be used in a purely
functional style, but doesn't force you into programming that way.
|
|
Brian Rogoff
|
What is a "functional language"?
To me, it has less to do with being side-effect free than with providing
"first class" functions.
I would also add block structure and lexical scope as criteria to really be
a functional language.
Does Dylan have first class functions, block structure, and lexical
scope? Yes, so I'd put it in there without hesitation.
> If Common Lisp and Scheme and OCaml are there (which
they are)
> then Dylan certainly should be too
I'm mostly an OCaml programmer these days, and I'd agree OCaml is
(not just) a functional programming language, as is Dylan.
> Like them Dylan has all the features needed to be
used in a purely >
functional style, but doesn't force you into programming that way.
A more interesting question IMO is to what extent a functional style is
used in common Dylan programming. My OCaml style is largely
functional but there is almost *always* some bit of imperative code, and
the use of exceptions (which some people, not me, consider non-
functional).
|
|
|
Honestly, my Dylan code is more functional than my Ocaml code. This
is because I find it easier to write in a state-passing or monadic style in
Dylan than in Caml.
I find Dylan nicer for writing state-passing code because of a nasty
habit: I care about memory allocation. Dylan's multiple return values can
be stack allocated, whereas using a tuple won't be. Even though I
*know* that I shouldn't care, I do. :) The combination of generic functions
makes a modular monadic style almost ridiculously easy to do. I tend to
cheat a bit, and use macros to eliminate the overhead of a monadic
style, too.
|
|
|
|
|
I started to look around and picked Dylan as my next language of choice
Lately I've stopped using Dylan, not because I want to stop using it, but rather
because I'm cramming functional programming into my head. I've temporarily
switched to using Haskell until I grok FP, after which I'll switch back to Dylan.
(Why did I switch to Haskell over Dylan to learn FP? Because the best way to
learn a paradigm is to be forced to use it. It's too easy to slip out of FP mode
with Dylan. I can't slip out of FP mode in Haskell.)
|
|
fun-principal
|
read
|
|
|
|
Roedy Green
|
Please define "block" and "lambda expressions"
|
|
Marty Hall
|
A lambda expression is a way of defining a function without associating
it with a function name.
The actual term "lambda" was borrowed from Alonzo Church's lambda
calculus, which was a formalism for describing functions and their
evaluation that predated programming.
I've used them in Lisp, Scheme, Dylan, and ML, and they are very,
VERY useful indeed.
Common Lisp and Dylan try to incorporate both OO and functional
programming, but in Scheme and ML the function as a data type is
considered more important than the object. (Gasp. Heresy!). As an
aside, a very interesting aside is that in a dynamically typed version of the
lambda calculus, you only need about 3 constructs to get complete
Turing computability. Surprisingly, you can define recursive procedures
without using function names or variables of any sort.
Anyhow, here's a pseudo Java example, passing an anonymous method
that gets assigned to a button's action() field. I'm using "Method" here
instead of "Lambda".
Button quitButton = new Button("Quit);
quitButton.action = new Method((Event e, Object o) { System.exit(0); });
I haven't used Smalltalk, but
I gather "Block" is similar.
|
|
functional-
principal
|
|
|
|
|
|
|
|
rob myers
|
Classes as a concept don't have to contain methods, and indeed
even in C++ you can view a virtual method as an entity that stretches
down through the class hierachy. Syntactically in C++, you
implement (non-inline) member functions outside the class curlies,
and then you have friend functions...
I *love* Dylan's Generic Function system. Current OO thinking
seems to regard Objects as consisting of funtionality, not data.
Priviledging methods/functions equally compared to data objects
makes this world-view easier to express (strangely) as functions
don't hang off data so much, and I feel it gives a more balanced view
of the world.
Java's broken, broken, broken "OK, you've inhehited ten ABCs now
code the funtionality" interface system is soooo weak (I program Java
for a living). Multiinheritance I can save time and effort, make elegant
designs or be mis-used like anything else. :-)
- Rob.
|
|
Michael T. Richter
|
> Classes as a concept don't have to contain methods,
> and indeed even in C++ you can view a virtual method
> as an entity that stretches down through the class
> hierachy.
This was the biggest switch I had to make in thinking about object-
orientation when switching to Dylan. I had beforehand -- because of
pollution caused by C++, Java, Eiffel, etc. -- always conflated the
mostly orthogonal issues of state encapsulation, access control and
functionality encapsulation into one "golden hammer" solution:
classes. It took looking into Dylan, Modula- 3 (to an extent) and
other such languages for me to even realize that an alternative
viewpoint was available.
Now, post-Dylan-switch, I map these concepts into different
containers. State encapsulation belongs to classes. Access control
belongs to libraries
and modules. Functionality encapsulation belongs to generic
methods. I find myself wrestling with the language less and the
problem domain more now. This, combined with access to some of
the cool features of functional programming (not to mention the ability
to effectively add new semantics to the language with hygenic
macros) has confirmed my selection.
Of course now I can't convince any of my colleagues of the benefits
of this switch. They see methods without a "self" or "this" (implied or
explicit) and the barriers snap up. "That's not object-oriented
programming!" is the endless refrain.
|
|
|
|
|
Dylan's Differing World View
The fundamental difference between the Dylan view of object behavior and that
espoused by Smalltalk hinges on how one elicits behavior. In the Smalltalk view,
classes contain an enumeration of the data members each instance will contain and
also contain the methods used by the class to implement messages it will receive.
The Dylan view, removes the methods from the classes, and groups them together in
what are termed generic functions. A generic function is associated with the
methods which implement it, rather than associating methods with the objects.
Dylan's view, though characterized by some as non-OO, supports a valid
and
reasonable view of how to achieve computation in an OO framework. In particular,
Dylan's view solves problems associated with more traditional message-passing
implementations. (See the double-dispatchwork-around cited by Budd in Chapter 8
as an example of something that can be avoided easily in Dylan.) Dylan's view also
supports multiple-inheritance in a straighforward and principled way.
|
|
|
|
Amit Patel
|
many problems solved by complicated features in a purely object-oriented language
are solved by a rich set of non-object features such as
- modules
- first class functions
- abstract data types
- parameteric polymorphsim (generics)
[Patel does this statement in his theis about Obstacl, but
it true for Dylan as well.]
|
|
Douglas
Auclair's
|
Dylan, like other object-oriented programming languages (OOPLs), has classes,
objects, functions and data. But what separates Dylan from most other well-known
OOPLs is that it combines covariant and contravariant inheritance. "Balderdash!" you
exclaim; what does this mean? Dylan allows you to associate functions with classes
without damaging the preexisting class interface. This allows you to modify behavior
of built-in classes, of your own classes, and classes that you do not have the source
code. In other words, Dylan incorporates the Visitor(331) design pattern directly and
naturally.
|
|
Isaac
Gouy
|
Behavior can be added to existing classes without subclassing or modifying the
source code of those classes. Access to the source code is not even required. This
is a direct result of the generic function object model.
|
|
Gregory
Sullivan
and
Jonathan
R.
Bachrach
|
Dylan is the most ambitious attempt to date to add modern syntactic extension
features to an infix language.
|
|
Ashley
Yakeley
|
In Dylan, everything is an object, a direct instance of exactly one class.
Dylan has union types, limited types and singletons, all of which can be used as
variable and constant types and specialising types in generic functions and
methods.
Dylan has libraries for hiding implementations, and the ability to seal classes,
generic functions and domains of generic functions to those libraries.
Dylan has no previous language legacy to support.
|
|
Jason
Trenouth
|
Interactive programming languages like Dylan, Common Lisp and Smalltalk provide
the kind of immediate feedback that emancipates developers and frees them to roam
over the application space without being constrained by having to build custom test
beds or utilize restricted scripting languages.
|
|
|
|
Based on
|
DYLAN- (Dynamic Languages) general-purpose, high-level programming
language. includes
- garbage collection,
- type-safety,
- error recovery,
- a module system, and
- a programmers control of run-time
extensibility of programs.
Invented by Apple Computer.
Uses one construct for simple purposes through multi-method dispatch.
DYLAN is dynamic, anything that is not flagged constant can be changed at run-
time.It's common for a DYLAN class to start off using generic (weak) types, and
to later refine the types to be specialized (strong).
In DYLAN, methods don't belong to classes, they are basically functions,
organized into generic functions. Proponents claim that this makes adding
functionality much easier than having to modify classes or create subclasses to
add new methods.
Functions can have both positional and keyword arguments.
Doesn't enforce information hiding by class like JAVA or C++, it enforces it by
module. Modules can import, export, and re-export names, and imported names
can be mapped to different names to avoid names clashes.
Each class contains some number of slots, which hold objects. DYLAN's objects
are alot like SMALLTALK's: both have languages with "objects all the way down",
even a simple number is an instance of a class.
Supports multiple inheritance without redundantacy, to encourage a mix-in style
programming. Can descend from a base class more than once through multiple
inheritance, but will still only contain one copy of the base class.
Compiles like C++, compiler optimizes out much of the object-dispatch and
dynamic overhead that plagued SMALLTALK.
|
|
|
Mark C. Chu-Carroll and
Lorry L Pollock in a
Technical Report about
P-Dylan (a Dylan-
version extended for
parallel programming)
|
|
|
|
|
|
|
|
|
|
|
John
Brewer
|
Give me a language like Dylan and an infrastructure like C/C++,
and I'll adopt it immediately! --
|
|
|
|
|
|
|
|
|
|
Jeff Dalton
|
I'm worried that Dylan may be repeating one of the
biggest mistakes of Lisp, namely that of supposing
people would rather move to a new Dylan world than
use Dylan in their existing worlds
I would also suggest that a successful language can
make a fancy environment for it seem like an excellent
thing, but not the other way around. Saying "use this
language becuase it has a great environment" works
less well.
|
|
|
|
|
|
|
|
|
|