Python and Viv · Records, classes and tuples
Tuples and unpacking
What to notice
return q, randq, r = f(a, b)read the same in both. Viv has no tuple value: a function returns several values and the caller unpacks them on a line of its own.divmod_floor(-7, 2) == (-4, 1)has no Viv form, so the test unpacks first.a, b = b, aswaps in both, andv[0], v[2] = v[2], v[0]swaps two elements: every value on the right is computed before any target is written.x, y, z = pointunpacks an array of exactly three elements; another length stops the run, as Python raisesValueError.for _ in range(n)has no_in Viv; the loop names its counter.- The generator expression
sum((x - mean) ** 2 for x in xs)is one array expression in Viv,sum((xs - mean) ^ 2): arithmetic between an array and a number applies to every element.
Python tuples.py · 48 lines
Viv tuples.viv · 56 lines
py2viv refuses tuples.py
1 return several values
4def divmod_floor(a, b):
5 q = a // b
6 return q, a - q * b
7
8q, r = divmod_floor(17, 5)
9print(q, r)
2def divmod_floor(a, b) {
3 q = a // b
4 return q, a - q * b
5}
6
7q, r = divmod_floor(17, 5)
8print(q, r)
py2viv refuses this program:
tuples.py:47:8: not numeric Python: a call of `divmod_floor`, which returns 2 values, used as one value (lifted by R5)
assert divmod_floor(-7, 2) == (-4, 1)
^^^^^^^^^^^^^^^^^^^
Unpack it on its own line: `a, b = divmod_floor(...)`.
1 construct outside the numeric subset (tools/py2viv/SUBSET.md) 2 swap without a temporary
12a, b = 1, 2
13a, b = b, a
14print(a, b)
11a, b = 1, 2
12a, b = b, a
13print(a, b)
(refused)
3 Fibonacci by pairs
17def fib_pair(n):
18 prev, cur = 0, 1
19 for _ in range(n):
20 prev, cur = cur, prev + cur
21 return prev, cur
22
23f10, f11 = fib_pair(10)
24print(f10, f11)
16def fib_pair(n) {
17 prev, cur = 0, 1
18 for k to n {
19 prev, cur = cur, prev + cur
20 }
21 return prev, cur
22}
23
24f10, f11 = fib_pair(10)
25print(f10, f11)
(refused)
4 statistics in one pass
27def mean_and_spread(xs):
28 n = len(xs)
29 mean = sum(xs) / n
30 var = sum((x - mean) ** 2 for x in xs) / n
31 return mean, var ** 0.5, n
32
33mean, sd, n = mean_and_spread([2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0])
34print(f"n = {n}, mean = {mean}, sd = {sd}")
28def mean_and_spread(xs) {
29 n = len(xs)
30 mean = sum(xs) / n
31 var = sum((xs - mean) ^ 2) / n
32 return mean, var ^ 0.5, n
33}
34
35mean, sd, n = mean_and_spread([2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0])
36print(f"n = {n:d}, mean = {mean!r}, sd = {sd!r}")
(refused)
5 unpack a list of known length
37point = [0.5, -1.5, 2.0]
38x, y, z = point
39print(x + y + z)
39point = [0.5, -1.5, 2.0]
40x, y, z = point
41print(fmt(x + y + z))
(refused)
6 swap two elements of a list
42v = [10, 20, 30]
43v[0], v[2] = v[2], v[0]
44print(v)
44v = [10, 20, 30]
45v[0], v[2] = v[2], v[0]
46print(v)
(refused)
7 checks
47assert divmod_floor(-7, 2) == (-4, 1)
48assert (f10, f11) == (55, 89)
49test "several results" {
50 dq, dr = divmod_floor(-7, 2)
51 assert_true(dq == -4 and dr == 1)
52 assert_true(f10 == 55 and f11 == 89)
53}
(refused)
What they print
identical — the two programs print the same text.
Dimmed lines are left out of the comparison. Each Viv test block prints one PASS line; the Python checks the same facts with assert, which prints nothing.
$ python3 tuples.py
3 22 155 89n = 8, mean = 5.0, sd = 2.01.0[30, 20, 10]
$ viv run tuples.viv
3 22 155 89n = 8, mean = 5.0, sd = 2.01.0[30, 20, 10]PASS several results