Python and Viv · Lists and growable arrays
Growing a list
What to notice
squares.append(x)issquares = append(squares, x). The append gives back the grown array and the program rebinds the name; a second name taken before the append keeps the old array.- The comprehensions are the same in both. A comprehension of numbers makes a Viv array;
squares[:HEAD] / 2would divide every element too. squares[-1]andsquares[:-1]count from the end in both.extendis a function that returns the joined array, asappendis.v in squaresanda if c else bread the same in both. On an array of numbersincompares as==does, so a NaN is in no array, as in NumPy.- A list of lists is a matrix in Viv. Appending a row to
[]makes it 1 by 3,shape(table)gives its size, andfor row in rows(table)walks its rows (for row in tablewould walk its numbers). - Viv's
printof an array writes whole numbers without.0;fmt(halves)writes each element in Python's form,[0.0, 0.5, 2.0, 4.5].
Python growable.py · 39 lines
Viv growable.viv · 48 lines
py2viv refuses growable.py
1 start empty and append
4squares = []
5N = 10
6for i in range(N):
7 squares.append(i * i)
8print(squares)
2squares = []
3N = 10
4for i to N {
5 squares = append(squares, i * i)
6}
7print(squares)
py2viv refuses this program:
growable.py:7:5: not numeric Python: list.append (lifted by R17)
squares.append(i * i)
^^^^^^^^^^^^^^^^^^^^^
py2viv changes a list (append, pop, insert, extend, remove, clear, reverse, sort) only when nothing else can hold it: bound only to new lists (`[]`, a list literal, a comprehension, list(...), sorted(...)) and read nowhere an alias could be taken (a second name, an argument, a container, a nested def); otherwise allocate the final size with np.zeros(n) and write by index.
growable.py:8:7: not numeric Python: printing a value of unknown type (it comes from a construct refused elsewhere)
print(squares)
^^^^^^^
Fix the refusal that produced it.
growable.py:11:21: not numeric Python: iterating over a value of unknown type
evens = [s for s in squares if s % 2 == 0]
^^^^^^^
Fix the refusal that produced it.
growable.py:12:7: not numeric Python: printing a value of unknown type (it comes from a construct refused elsewhere)
print(evens, len(evens))
^^^^^
Fix the refusal that produced it.
growable.py:15:26: not numeric Python: iterating over a value of unknown type
halves = [s / 2 for s in squares[:4]]
^^^^^^^^^^^
Fix the refusal that produced it.
growable.py:16:7: not numeric Python: printing a value of unknown type (it comes from a construct refused elsewhere)
print(halves)
^^^^^^
Fix the refusal that produced it.
growable.py:20:1: not numeric Python: list.extend (lifted by R17)
squares.extend(more)
^^^^^^^^^^^^^^^^^^^^
py2viv changes a list (append, pop, insert, extend, remove, clear, reverse, sort) only when nothing else can hold it: bound only to new lists (`[]`, a list literal, a comprehension, list(...), sorted(...)) and read nowhere an alias could be taken (a second name, an argument, a container, a nested def); otherwise allocate the final size with np.zeros(n) and write by index.
growable.py:21:21: not numeric Python: printing a value of unknown type (it comes from a construct refused elsewhere)
print(len(squares), squares[-1])
^^^^^^^^^^^
Fix the refusal that produced it.
growable.py:22:1: not numeric Python: an empty list grown and also bound to something else
squares = squares[:-1]
^^^^^^^
py2viv grows a list bound only to new lists and read only by `len`, indexing, loops, conditions, `return` and its own methods; Viv's `lst = append(lst, x)` gives a new array, so an alias would not see the change.
growable.py:23:21: not numeric Python: printing a value of unknown type (it comes from a construct refused elsewhere)
print(len(squares), squares[-1])
^^^^^^^^^^^
Fix the refusal that produced it.
growable.py:27:34: not numeric Python: `in` of a value of unknown type
print(v, "is in the list" if v in squares else "is not in the list")
^^^^^^^^^^^^
Test membership in a list or an array.
growable.py:38:8: not numeric Python: `==` of a Python list or a tuple
assert evens == [0, 4, 16, 36, 64]
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Python compares lists and tuples as a whole (in order, or raises TypeError against a number); make it a NumPy array to compare entry by entry.
12 constructs outside the numeric subset (tools/py2viv/SUBSET.md) 2 a comprehension with a condition
11evens = [s for s in squares if s % 2 == 0]
12print(evens, len(evens))
10evens = [s for s in squares if s % 2 == 0]
11print(evens, len(evens))
(refused)
3 a comprehension that maps
15halves = [s / 2 for s in squares[:4]]
16print(halves)
14HEAD = 4
15halves = [s / 2 for s in squares[:HEAD]]
16print(fmt(halves))
(refused)
4 extend, and drop the last element
19more = [100, 121]
20squares.extend(more)
21print(len(squares), squares[-1])
22squares = squares[:-1]
23print(len(squares), squares[-1])
19more = [100, 121]
20squares = extend(squares, more)
21print(len(squares), squares[-1])
22squares = squares[:-1]
23print(len(squares), squares[-1])
(refused)
5 membership and sums
26for v in [49, 50]:
27 print(v, "is in the list" if v in squares else "is not in the list")
28print(sum(squares), sum(squares) / len(squares))
26for v in [49, 50] {
27 print(v, "is in the list" if v in squares else "is not in the list")
28}
29print(sum(squares), fmt(sum(squares) / len(squares)))
(refused)
6 rows onto a table
31table = []
32for i in range(1, 4):
33 table.append([i, i * i, i ** 3])
34for row in table:
35 print(row)
32table = []
33ROWS = 4
34for i from 1 to ROWS {
35 table = append(table, [i, i * i, i ^ 3])
36}
37for row in rows(table) {
38 print(row)
39}
(refused)
7 checks
38assert evens == [0, 4, 16, 36, 64]
39assert len(table) == 3 and len(table[0]) == 3
42test "growable" {
43 assert_true(all(evens == [0, 4, 16, 36, 64]))
44 assert_true(shape(table)[0] == 3 and shape(table)[1] == 3)
45}
(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 growable.py
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81][0, 4, 16, 36, 64] 5[0.0, 0.5, 2.0, 4.5]12 12111 10049 is in the list50 is not in the list385 35.0[1, 1, 1][2, 4, 8][3, 9, 27]
$ viv run growable.viv
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81][0, 4, 16, 36, 64] 5[0.0, 0.5, 2.0, 4.5]12 12111 10049 is in the list50 is not in the list385 35.0[1, 1, 1][2, 4, 8][3, 9, 27]PASS growable