This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

Python and Viv · Lists and growable arrays

Slices, copies and aliases

What to notice

Open the Viv in the workbench The atlas of the Viv py2viv refuses this Python (the reason is in its column).
Python slicing.py · 41 lines
Viv slicing.viv · 58 lines
py2viv refuses slicing.py
1 imports
4import numpy as np
2# nothing to import: arrays are part of the language
py2viv refuses this program:
slicing.py:10:60: not numeric Python: a slice with the step `STEP`
    print(a[2:5].tolist(), a[:3].tolist(), a[7:].tolist(), a[::STEP].tolist())
                                                               ^^^^
  Viv's slices take a literal step of 1 or more; a negative step walks backward, which they do not. Write the loop over the indices.
slicing.py:18:1: not numeric Python: a write through `part`, which is a slice of another array
    part[0] = 99.0
    ^^^^^^^
  Rows and slices are copies in Viv; write into the original array: `A[i, j] = ...`.
2 constructs outside the numeric subset (tools/py2viv/SUBSET.md)
2 slices of an array
7N = 10
8STEP = 3
9a = np.arange(float(N))
10print(a[2:5].tolist(), a[:3].tolist(), a[7:].tolist(), a[::STEP].tolist())
5N = 10
6STEP = 3
7a = zeros(N)
8for i to N {
9 a[i] = i
10}
11print(fmt(a[2:5]), fmt(a[:3]), fmt(a[7:]), fmt(a[::STEP]))
(refused)
3 the last elements
13print(a[-1], a[-3:].tolist())
14print(fmt(a[-1]), fmt(a[-3:]))
(refused)
4 a slice is a view in NumPy and a copy in Viv
16d = np.zeros(4)
17part = d[1:3]
18part[0] = 99.0
19print("d[1] after a write through the slice:", d[1])
17D = 4
18d = zeros(D)
19part = d[1:3]
20part[0] = 99.0
21print("d[1] after a write through the slice:", fmt(d[1]))
(refused)
5 assignment shares the array
22c = a
23c[0] = -1.0
24print(a[0])
24c = a
25c[0] = -1.0
26print(fmt(a[0]))
(refused)
6 write into a slice
27a[5:8] = 0.0
28print(a.tolist())
29a[5:8] = 0.0
30print(fmt(a))
(refused)
7 where is the largest value
31x = np.array([3.0, 8.5, -2.0, 8.5, 1.0])
32k = int(np.argmax(x))
33print(k, x[k])
33x = [3.0, 8.5, -2.0, 8.5, 1.0]
34k = 0
35for i to len(x) {
36 if x[i] > x[k] {
37 k = i
38 }
39}
40print(k, fmt(x[k]))
(refused)
8 running sums
36running = np.cumsum(x)
37print(running.tolist())
43running = zeros(len(x))
44total = 0.0
45for i to len(x) {
46 total += x[i]
47 running[i] = total
48}
49print(fmt(running))
(refused)
9 checks
40assert a[0] == -1.0
41assert running[-1] == np.sum(x)
52test "slices" {
53 assert_true(a[0] == -1.0)
54 assert_true(running[-1] == sum(x))
55}
(refused)

What they print

differs — One line differs and is left out of the comparison. A NumPy slice is a view, so writing into it changes the array it came from (d[1] becomes 99.0); a Viv slice is a copy, so d[1] stays 0.0.

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. The remaining lines match.

$ python3 slicing.py

[2.0, 3.0, 4.0] [0.0, 1.0, 2.0] [7.0, 8.0, 9.0] [0.0, 3.0, 6.0, 9.0]
9.0 [7.0, 8.0, 9.0]
d[1] after a write through the slice: 99.0
-1.0
[-1.0, 1.0, 2.0, 3.0, 4.0, 0.0, 0.0, 0.0, 8.0, 9.0]
1 8.5
[3.0, 11.5, 9.5, 18.0, 19.0]

$ viv run slicing.viv

[2.0, 3.0, 4.0] [0.0, 1.0, 2.0] [7.0, 8.0, 9.0] [0.0, 3.0, 6.0, 9.0]
9.0 [7.0, 8.0, 9.0]
d[1] after a write through the slice: 0.0
-1.0
[-1.0, 1.0, 2.0, 3.0, 4.0, 0.0, 0.0, 0.0, 8.0, 9.0]
1 8.5
[3.0, 11.5, 9.5, 18.0, 19.0]
PASS slices