A Dylan Primer for Scheme Programmers

This document was originally authored by Jonathan Sobel.

Almost everything you already do in Scheme has a direct counterpart in Dylan.

Note

If one column contains N/A, then that language has no corresponding direct way to express what is in the other column.

Literals

Scheme

Dylan

#t
#t
#f
#f
23
23
#b1011
#b1011
#o644
#o644
#x2A5F
#x2A5F
-4/5

N/A

6.02E23
6.02E23
#\a
'a'
#\newline
'\n'
"Hello"
"Hello"
"Hello\n"
"Hello\n"
'apple
#"apple"
apple:
'|two words|
#"two words"
'(1 #\a dog)
#(1, 'a', #"dog")
#(5 10 15)
#[5, 10, 15]
`(1 2 ,x ,@y)

N/A

Syntax

Note that, in Dylan, any words after an end (e.g. end method) are optional.

Scheme

Dylan

(define var exp)
define variable var = exp
define constant var = exp
(f x y z)
f(x, y, z)
(begin 1 2 3)
begin 1; 2; 3; end
begin 1; 2; 3 end
(quote datum)

N/A

(lambda (x y . z)
  (say "hello")
  (f x y z))
method (x, y, #rest z)
  say("hello");
  f(x, y, z);
end method
(begin
  (define x 5)
  body)
begin
  let x = 5;
  body
end
(define-values (x y) exp)
let (x, y) = exp;
(let-values (((x y)
              (values 5 6)))
  (f x y))
let (x, y) = values(5, 6);
f(x, y)
(letrec ((f (lambda (x)
        f-body)
   )
   (g (lambda (y z)
        g-body)
   ))
  body)
local method f (x)
  f-body
end method f,
method g (y, z)
  g-body
end method g;
body
(if test
    (begin then1
     then2)
    (begin else1
     else2)
)
if (test)
  then1;
  then2;
else
  else1;
  else2;
end if
(set! var value)
var := value
(and a b c)
a & b & c
(or a b c)
a | b | c
(cond
 (test1 result1)
 (test2 result2)
 (else result)
)
case
  test1 => result1;
  test2 => result2;
  otherwise => result;
end case
(case exp
 ((a 2) result1)
 (('a' 'b') result2)
 (else result)
)
select (exp)
  #"a", 2 => result1;
  'a', 'b' => result2;
  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)
     (var2 init2 step2))
    (test result)
  body
)
for (var1 = init1 then step1,
     var2 = init2 then step2,
     until: test)
  body
finally result
end for

Predefined functions

These are organized based on the “Standard Procedures” section of R4RS.

Boolean functions

(not obj)
~ obj
~obj
(boolean? obj)
instance?(obj, <boolean>)

Equivalence predicates

(eqv? x y)
x == y
(eq? x y)

N/A

(equal? x y)
x = y

Pairs and Lists

(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)
head(ls) := val
(set-cdr! ls val)
tail-setter(val, ls)
tail(ls) := val
(cadadr ls)
N/A
(null? obj)
instance?(obj, <empty-list>)
obj = #()
empty?(ls) // most common
(list? obj)
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: \==)

Symbols

(symbol? obj)
instance?(obj, <symbol>)
(symbol->string sym)
as(<string>, sym)
(string->symbol str)
as(<symbol>, str)

Numerical operations

(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>)
integral?(num)
(= n1 n2)
n1 = n2
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
-x
(expt 2 16)
2 ^ 16

[Most of the standard Scheme numeric functions (e.g. max, remainder) are defined similarly in Dylan. No need to list them all here.]

Characters

(char? obj)
instance?(obj, <character>)
(char=? char1 char2)
char1 = char2
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)

Strings

(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)
str[k]
(string-set! str k char)
element-setter(char, str, k)
str[k] := char
(string=? str1 str2)
str1 = str2
(string<? str1 str2)
str1 < str2
(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)
copy-sequence(str)
(string-fill! str char)
fill!(str, char)

Vectors

(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)
vec[k]
(vector-set! vec k obj)
element-setter(obj, vec, k)
vec[k] := obj
(vector->list vec)
as(<list>, vec)
(list->vector list)
as(<vector>, list)
(vector-fill! vec obj)
fill!(vec, obj)

Control Features

(procedure? obj)
instance?(obj, <function>)
(apply proc arg1 arg2 args)
apply(proc, arg1, arg2, args)
(map proc list1 list2 ...)
map(proc, list1, list2, ...)
(vector-map proc
            vec1 vec2 ...)
map(proc, vec1, vec2, ...)
(string-map
   string1 string2 ...)
map(proc, string1, string2)
(for-each proc list1 list2)
do(proc, list1, list2)

Continuations

Continuations have indefinite extent in Scheme but have dynamic extent in Dylan. Also, whereas call/cc is a function, Dylan uses special syntax to grab a continuation.

(call/cc
  (lambda (k)
    body))
block (k)
  body
end block
(call/cc
  (lambda (k)
    (dynamic-wind
      (lambda () #f)
      (lambda () body)
      (lambda ()
         cleanup-stuff))))
block (k)
  body
cleanup
  cleanup-stuff
end block