Almost everything you already do in Scheme can be translated easily into Dylan(tm). In fact, with one exception, Dylan is a proper superset of Scheme. The one exception is that continuations have indefinite extent in Scheme and dynamic extent in Dylan. Some individual implementations of Dylan might provide a mechanism for producing continuations with indefinite extent, making all Scheme programs be Dylan programs, too. (Of course, you won't be taking full advantage of the power of Dylan if you only write Scheme programs in it.)
This document is really just a large table in two columns. On the
left, you will see a Scheme expression, and on the right, its Dylan
counterpart. If one column contains N/A, then that
language has no corresponding direct way to express what is in the
other column.
Please remember, there is much more to Dylan than what you'll find here! For example, this document doesn't show you how to define new classes or create generic functions (functions which support ad hoc polymorphic behavior). This document is only intended to help ease your transition from Scheme to Dylan.
Scheme Dylan
#t #t #f #f 23 23 #b1011 #b1011 #o644 #o644 #x2A5F #x2A5F -4/5 -4/5 6.02E23 6.02E23 #\a 'a' #\newline '\n' (Dylan supports \a, \b, \e, \f, \n, \r, \t, and \0) "Hello" "Hello" N/A "Hello\n" 'apple #"apple" or apple: N/A #"two words" (Think "hashed string"...) '(1 #\a dog) #(1, 'a', #"dog") '#(5 10 15) #[5, 10, 15] `(1 2 ,x ,@y) N/A
Note that, in Dylan, any words after an end (e.g.
end method) are optional.
(define var exp) define variable var = exp
or define constant var = exp
(f x y z) f(x, y, z)
(begin 1 2 3) begin 1; 2; 3; end
or begin 1; 2; 3 end
(quote datum) N/A
(lambda (x y . z) method (x, y, #rest z)
(say "hello") say("hello");
(f x y z) f(x, y, z);
) end method
(let ((x 5)) let x = 5;
body) body
(Scope ends at next "body-ender.")
N/A let (x, y) = exp;
(Binds multiple values returned by exp.)
(let ((x 5) (y 6)) let (x, y) = values(5, 6);
(f x y)) f(x, y)
(letrec ((f (lambda (x) local method f (x)
f-body) f-body
) end method f,
(g (lambda (y z) method g (y, z)
g-body) g-body
)) end method g;
body) body
(if test if (test)
(begin then1 then1;
then2) then2;
(begin else1 else
else2) else1;
) else2;
end if
(set! var value) var := value
(and a b c) a & b & c
(or a b c) a | b | c
(cond case
(test1 result1) test1 => result1;
(test2 result2) test2 => result2;
(else result) otherwise => result;
) end case
(case exp select (exp)
((a 2) result1) #"a", 2 => result1;
(('a' 'b') result2) 'a', 'b' => result2;
(else result) otherwise => result;
) end select
N/A select (exp by comparison-func)
f(x) => result1;
g(y), h(z) => result2;
otherwise => result;
end select
(do ((var1 init1 step1) for (var1 = init1 then step1,
(var2 init2 step2)) var2 = init2 then step2,
(test result) until: test)
body body
) finally result
end for
These are organized based on the "Standard Procedures" section of R4RS.
(not obj) ~ obj or ~obj (boolean? obj) instance?(obj, <boolean>) (eqv? x y) x == y (eq? x y) N/A (equal? x y) x = y (pair? obj) instance?(obj, <pair>) (cons x y) pair(x, y) (car ls) head(ls) (cdr ls) tail(ls) (set-car! ls val) head-setter(val, ls) or head(ls) := val (set-cdr! ls val) tail-setter(val, ls) or tail(ls) := val (cadadr ls) N/A (null? obj) literally instance?(obj, <empty-list>) or obj = #() but the most common usage is empty?(ls) (list? obj) approximately instance?(obj, <list>) (list x y z) list(x, y, z) (length ls) size(ls) (append ls1 ls2 ls3) concatenate(ls1, ls2, ls3) (reverse ls) reverse(ls) (list-ref ls n) element(ls, n) (member obj ls) member?(obj, ls) (memv obj ls) member?(obj, ls, test: \==) (symbol? obj) instance?(obj, <symbol>) (symbol->string sym) as(<string>, sym) (string->symbol str) as(<symbol>, str) (number? obj) instance?(obj, <number>) (complex? obj) instance?(obj, <complex>) (real? obj) instance?(obj, <real>) (rational? obj) instance?(obj, <rational>) (integer? obj) instance?(obj, <integer>) or integral?(num) (= n1 n2) n1 = n2 or n1 == n2 (< n1 n2) n1 < n2 (> n1 n2) n1 > n2 (<= n1 n2) n1 <= n2 (>= n1 n2) n1 >= n2 (zero? n) zero?(n) (positive? n) positive?(n) (negative? n) negative?(n) (odd? i) odd?(i) (even? i) even?(i) (+ 1 2 3) 1 + 2 + 3 (* 1 2 3) 1 * 2 * 3 (- 5 3) 5 - 3 (/ 2.3 1.7) 2.3 / 1.7 (- x) - x or -x (expt 2 16) 2 ^ 16 [Most of the standard Scheme numeric functions (e.g. max, remainder) are defined simlarly in Dylan. I see no need to list them all here.] (char? obj) instance?(obj, <character>) (char=? char1 char2) char1 = char2 or char1 == char2 (char<? char1 char2) char1 < char2 (char>? char1 char2) char1 > char2 (char<=? char1 char2) char1 <= char2 (char>=? char1 char2) char1 >= char2 (char->integer char) as(<integer>, char) (integer->char n) as(<character>, n) (char-upcase char) as-uppercase(char) (char-downcase char) as-lowercase(char) (string? obj) instance?(obj, <string>) (make-string k char) make(<string>, size: k, fill: char) (string char ...) N/A (string-length str) size(str) (string-ref str k) element(str, k) or str[k] (string-set! str k char) element-setter(char, str, k) or str[k] := char (string=? str1 str2) str1 = str2 (string<? str1 str2) str1 < str2 etc. (substring str start end) copy-sequence(str, start: start, end: end) (string-append str1 str2) concatenate(str1, str2) (string->list str) as(<list>, str) (list->string chars) as(<string>, chars) (string-copy str) shallow-copy(str) or copy-sequence(str) (string-fill! str char) fill!(str, char) (vector? obj) instance?(obj, <vector>) (make-vector k fill) make(<vector>, size: k, fill: fill) (vector obj ...) vector(obj, ...); (vector-length vec) size(vec) (vector-ref vec k) element(vec, k) or vec[k] (vector-set! vec k obj) element-setter(obj, vec, k) or vec[k] := obj (vector->list vec) as(<list>, vec) (list>vector list) as(<vector>, list) (vector-fill! vec obj) fill!(vec, obj) (procedure? obj) instance?(obj, <function>) (apply proc arg1 arg2 args) apply(proc, arg1, arg2, args) (map proc list1 list2) map(proc, list1, list2) N/A map(proc, vec1, vec2) N/A map(proc, string1, string2) (for-each proc list1 list2) do(proc, list1, list2)
As I mentioned before, continuations have dynamic extent in Dylan.
Also, whereas call/cc is a function, Dylan uses a syntax
form to grab a continuation.
(call/cc block (k)
(lambda (k) body
body)) end block
(call/cc block (k)
(lambda (k) body
(dynamic-wind cleanup
(lambda () #f) cleanup-stuff
(lambda () end block
body)
(lambda ()
cleanup-stuff))))