A Dylan Primer for Python Programmers¶
Note
If one column contains N/A, then that language has no corresponding direct way to express what is in the other column.
Literals¶
Python |
Dylan |
---|---|
True
|
#t
|
False
|
#f
|
23
|
23
|
0b1011
|
#b1011
|
0o644
|
#o644
|
0x2A5F
|
#x2A5F
|
6.02e+23
|
6.02e+23 // double float
6.02s+23 // single float
6.02d+23 // double float
|
N/A No individual characters other than integer character codes |
'a'
'\n'
|
'Hello'
'Hello\n'
|
"Hello"
"Hello\n"
|
s = '''Hi, from
python'''
# No Rectangle rule
s = '''
Hi, from
Python
'''
|
let s = """
Hi, from
Dylan
""";
// Rectangle rule support
let s = """
Hi, from
Dylan
""";
|
N/A Not real symbols but strings are interned |
#"apple"
apple:
|
N/A No symbols |
#"two words"
|
(1, 'a', 'dog')
|
N/A No tuples (see multiple values) |
[5, 10, 15]
|
#[5, 10, 15]
|
Syntax¶
Note
In Dylan, any words after an end
(e.g. end method
) are
optional but, if present, must match the corresponding “begin”
word.
Python |
Dylan |
---|---|
var = exp
VAR = exp # Convention
|
let var = exp;
var := exp;
define variable var = exp;
define variable var :: type = exp;
define constant var = exp;
|
f(x, y, z)
|
f(x, y, z)
|
1
2
3
|
begin 1; 2; 3; end
begin 1; 2; 3 end
|
lambda x, y, *z:
print('hello')
return f(x, y, z)
|
method (x, y, #rest z)
format-out("hello");
f(x, y, z)
end method
|
x, y = exp
|
let (x, y) = exp
|
x, y = (5, 6)
f(x, y)
|
let (x, y) = values(5, 6);
f(x, y)
|
def foo():
def f(x):
f-body
def g(y, z):
g-body
body
|
define function foo ()
local method f (x)
f-body
end,
method g (y, z)
g-body
end;
body
end;
|
if test:
then1
then2
else:
else1
else2
|
if (test)
then1;
then2;
else
else1;
else2;
end if
|
a and b and c
|
a & b & c
|
a or b or c
|
a | b | c
|
if test1:
result1
elif test2:
result2
else:
result
|
case
test1 => result1;
test2 => result2;
otherwise => result
end case
|
if exp in (1, 2):
result1
elif exp in ('a', 'b'):
result2
else:
result
|
select (exp)
1, 2 => result1;
'a', 'b' => result2;
otherwise => result
end select
|
c = comparison-func(exp)
if c == 'foo':
result1
elif c == 'bar':
result2
else:
result
|
select (exp by comparison-func)
"foo" => result1;
"bar" => result2;
otherwise => result
end select
|
var1 = init1
var2 = init2
while not test:
body
var1 = step1
var2 = step2
return var1
|
for (var1 = init1 then step1,
var2 = init2 then step2,
until: test)
body
finally var1
end for
|
Predefined functions¶
Boolean functions¶
Python |
Dylan |
---|---|
not obj
|
~ obj
~obj
|
isinstance(obj, bool)
|
instance?(obj, <boolean>)
|
Equivalence predicates¶
Python |
Dylan |
---|---|
x == y
|
x = y
|
x is y
|
x == y
|
Symbols¶
Python |
Dylan |
---|---|
N/A |
instance?(obj, <symbol>)
|
N/A |
as(<string>, sym)
|
as(<symbol>, str)
|
Numerical operations¶
Python |
Dylan |
---|---|
isinstance(obj,
(int, float, complex))
|
instance?(obj, <number>)
|
isinstance(obj, complex)
|
instance?(obj, <complex>)
|
isinstance(obj,
(int, float))
|
instance?(obj, <real>)
|
isinstance(obj, int) or
(isinstance(obj, float) and
obj == int(obj))
|
instance?(obj, <rational>)
|
isinstance(obj, int)
|
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
|
n == 0
0 == 0.0 # True
|
zero?(n)
0 == 0.0 // #f
|
n > 0
|
positive?(n)
|
n < 0
|
negative?(n)
|
i % 2 != 0
|
odd?(i)
|
i % 2 == 0
|
even?(i)
|
1 + 2 + 3
|
1 + 2 + 3
|
1 * 2 * 3
|
1 * 2 * 3
|
5 - 3
|
5 - 3
|
1 / 2 # 0.5
|
1 / 2 // error
1.0 / 2 // 0.5
truncate/(1, 2) // 0
ceiling/(1, 2) // 1
floor/(1,2) // 0
|
-x
|
- x
-x
|
2 ** 16
|
2 ^ 16
|
max(1, 2, 3)
max([1, 2, 3])
|
max(1, 2, 3)
apply(max, #(1, 2, 3))
|
5 % 2
|
remainder(5, 2)
|
Characters¶
Python |
Dylan |
---|---|
isinstance(obj, str) and
len(obj) == 1
|
instance?(obj, <character>)
|
char1 == char2
|
char1 == char2
|
char1 < char2
|
char1 < char2
|
char1 > char2
|
char1 > char2
|
char1 <= char2
|
char1 <= char2
|
char1 >= char2
|
char1 >= char2
|
ord(char)
|
as(<integer>, char)
|
chr(n)
|
as(<character>, n)
|
char.upper()
|
as-uppercase(char)
|
char.lower()
|
as-lowercase(char)
|
Strings¶
Python |
Dylan |
---|---|
isinstance(obj, str)
|
instance?(obj, <string>)
|
'x' * k
|
make(<string>, size: k, fill: char)
|
"".join('a', 'b', 'c'])
|
as(<string>, #['a', 'b', 'c'])
|
len(str)
|
size(str)
str.size
|
str[k]
|
element(str, k)
str[k]
|
# Strings are immutable
|
element-setter(char, str, k)
str[k] := char
|
str1 == str2
|
str1 = str2
|
str1 < str2
|
str1 < str2
|
str[start:end]
|
copy-sequence(str, start: start, end: end)
|
str1 + str2
|
concatenate(str1, str2)
|
list(str)
|
as(<list>, str)
|
list(str)
|
as(<string>, chars)
|
copy(str)
|
shallow-copy(str)
copy-sequence(str)
|
# Strings are immutable
|
fill!(str, char)
|
Vectors¶
Python |
Dylan |
---|---|
isinstance(obj, list)
|
instance?(obj, <vector>)
|
[fill] * k
|
make(<vector>, size: k, fill: fill)
|
[obj, ...]
|
vector(obj, ...)
|
len(vec)
|
size(vec)
vec.size
|
vec[k]
|
element(vec, k)
vec[k]
|
vec[k] = obj
|
element-setter(obj, vec, k)
vec[k] := obj
|
list(vec)
|
as(<list>, vec)
|
# Uses lists for both
list(list)
|
as(<vector>, list)
|
for i in range(len(vec)):
vec[i] = obj
|
fill!(vec, obj)
|
Control Features¶
Python |
Dylan |
---|---|
callable(obj)
|
instance?(obj, <function>)
|
proc(arg1, arg2, *args)
|
apply(proc, arg1, arg2, args)
|
map(proc, list1, list2, ...)
# returns iterator in
# Python 3
|
map(proc, list1, list2, ...)
|
map(proc, vec1, vec2, ...)
|
map(proc, vec1, vec2, ...)
|
map(proc, str1, str2)
|
map(proc, str1, str2)
|
for a,b in zip(list1, list2):
proc(a, b)
|
do(proc, list1, list2)
|
Continuations¶
Python doesn’t have first-class continuations like Scheme’s
call/cc
, and Dylan’s block
syntax is more like structured
exception handling or generators.
Here are approximate equivalents:
Python |
Dylan |
---|---|
def example():
try:
body()
except Error as e:
handle_error()
finally:
cleanup_stuff()
|
block (k)
body
exception (e :: <error>)
handle-error()
cleanup
cleanup-stuff
end block
|
N/A |
define function top ()
block (exit-block)
bar(exit-block);
format-out("You won't see this.\n");
end;
format-out("You WILL see this.\n");
end;
define function bar (thunk)
thunk()
end;
top();
|
Keyword arguments¶
Python |
Dylan |
---|---|
def wrapper_fn (a, b, c, **keys):
do_stuff(a, b, c)
return wrapped_fn(**keys)
def wrapped_fn (one = 1, two = 2, three = 3):
return [one, two, three]
|
define method wrapper-fn (a, b, c, #rest keys)
do-stuff(a, b, c);
apply(wrapped-fn, keys)
end;
define method wrapped-fn
(#key one = 1, two = 2, three = 3)
list(one, two, three)
end;
|
Python collects any number of keyword arguments into a dictionary. In
Dylan, #rest keys
collects the remaining arguments, not into a
dictionary, but into a vector (like a property list or plist):
alternating symbol-value pairs.