Due on 12 February by 8:00 PM, submit a file Asst2.dyl
containing class, function, and method definitions necessary
to implement a class <egg-timer> that can
be used by the following main program:
define method main ()
let x = read-char();
let e = make ();
until (x == 'q')
select (x)
'c' => press (e.c-button);
's' => press (e.s-button);
'm' => press (e.m-button);
otherwise => print ("I don't know which button that is.");
end select;
x := read-char (); // to discard carriage return
x := read-char ();
end until;
values (); // to return no printable value
end method main;
Make sure to use dylan mode for editing dylan programs in emacs.
You can add the following to the bottom of your .emacs file to
make sure
dylan mode is employed whenever you edit a program with filename
extension .dyl:
(setq auto-mode-alist (append (list (cons "\\.dyl$" 'dylan-mode))
auto-mode-alist))
(autoload 'dylan-mode "dylan-mode" "Dylan Editing Mode" t)
(setq load-path (cons (expand-file-name "/cis/homes/jnw/emacs")
load-path))
Make sure you use marlais mode to get a dylan listener within
an emacs session. You do this by adding the following at the
bottom of your .emacs file:
(autoload 'run-dylan "marlais" "Run an inferior Dylan process." t)
Then, when you want to execute a marlais interpreter from an emacs
buffer, you execute the emacs command M-x run-dylan.
Find out about manipulating multiple windows in emacs
from the Files menu item and using multiple buffers
with the Buffers menu.
Make sure you either link to ~jnw/bin/sun4/marlais from a directory
in your execution path, or change your .cshrc file to include
set path = ($path ~jnw/bin/sun4)
More on Generic Functions
One more example of generic function use. Consider the factorial
function.
define generic factorial (n :: ) => result :: ;
One can define multiple methods for factorial, because method dispatch
is based on the type, not the class of the
arguments in the method invocation.
The usual case treated by the factorial function is the following:
define method factorial (n :: )
n * factorial (n - 1);
end method factorial;
The previous factorial function doesn't work if its argument is 0.
We can create an argument whose type is the single value
0. (Such a type can be created by evaluating the expression
singleton (value)).
define method factorial (n == 0)
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(, max: -1))
error ("factorial: Bad argument", n);
end method factorial;
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>?
Using Message Passing Style in Dylan
The function curry is used to transform a function
of n arguments into a function of n - 1
arguments by fixing the first argument to some specific value.
Consider the function \+. It takes two arguments.
If we curry the first argument, then we must fix it
to some particular value. Find out the value of each of the
following expressions:
3
\+
curry
curry (\+, 3)
curry (\+, 3) (4)
What if we define a constant to have curry (\+, 3)
as its value? What will it do when we apply it?
Now consider the following class definition:
define class (
We can make this class employe message-passing syntax for
the behavior called message by currying a function whose
first argument is of type <c>. Consider the
following:
define method do-message (self :: , x :: )
self.s + x;
end method do-message;
define method message (self :: )
curry (do-message, self);
end method message;