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 · Basics

Functions

What to notice

Open the Viv in the workbench The atlas of the Viv py2viv translates this Python; the translation prints the same output.
Python functions.py · 38 lines
Viv functions.viv · 49 lines
py2viv translated from functions.py
What py2viv adds before the program
(nothing)
(nothing)

63 lines: a header and the guard functions its translation calls

1###
2Translated from functions.py by py2viv 0.2.0 (numeric Python -> Viv).
3Python source sha256: ecc2eebd61cb15540a9c15d25b67cd0df8fd886b44a0f263632499f7ef242022
4Each print(...) is one print(...) line; fmt(x) writes a float as Python's repr does.
5A `raise`, a failed assert and every guard `stop` with Python's exception line.
6###
7
8#| 0, 1, ..., n - 1.
9def py_iota(n) {
10 a = zeros(n)
11 for i to n {
12 a[i] = i
13 }
14 return a
15}
16
17#| Every entry of a real array, row-major, as a vector (a copy).
18def py_flat(a: Arr) {
19 return take(a, py_iota(numel(a)))
20}
21
22#| a / b with a float: ZeroDivisionError on a zero divisor.
23def py_div_f(a, b) {
24 if b == 0 {
25 stop("ZeroDivisionError: float division by zero")
26 }
27 return a / b
28}
29
30#| CPython's builtin sum of a float array or list before 3.12: left to right from 0.0
31#| (Viv's own sum adds in NumPy's pairwise order).
32def py_lsum(a: Arr) {
33 s = 0.0
34 for i to len(a) {
35 s += a[i]
36 }
37 return s
38}
39
40#| Python's max over a sequence: the first entry, replaced by each later one that is greater
41#| (so a NaN first stays, a NaN later is skipped, and of -0.0 and 0.0 the first wins).
42def py_bmax(a: Arr) {
43 f = py_flat(a)
44 m = f[0]
45 for i from 1 to len(f) {
46 if f[i] > m {
47 m = f[i]
48 }
49 }
50 return m
51}
52
53#| Python's min over a sequence (the first of equals wins).
54def py_bmin(a: Arr) {
55 f = py_flat(a)
56 m = f[0]
57 for i from 1 to len(f) {
58 if f[i] < m {
59 m = f[i]
60 }
61 }
62 return m
63}
1 a function with a default argument
4def greet(name, greeting="hello"):
5 """A greeting for one person."""
6 return f"{greeting}, {name}!"
7
8print(greet("Ada"))
9print(greet("Grace", "hi"))
10print(greet("Alan", greeting="good morning"))
2def greet_with(name, greeting) {
3 "A greeting for one person."
4 return f"{greeting}, {name}!"
5}
6
7def greet(name) {
8 return greet_with(name, "hello")
9}
10
11print(greet("Ada"))
12print(greet_with("Grace", "hi"))
13print(greet_with("Alan", "good morning"))
68#| A greeting for one person.
69def greet(name, greeting) {
70 return greeting + ", " + name + "!"
71}
72print(greet("Ada", "hello"))
73print(greet("Grace", "hi"))
74print(greet("Alan", "good morning"))
2 several results
13def min_max_mean(xs):
14 lo = min(xs)
15 hi = max(xs)
16 return lo, hi, sum(xs) / len(xs)
17
18lo, hi, mean = min_max_mean([4.0, 1.0, 7.0, 2.0])
19print(lo, hi, mean)
16def min_max_mean(xs) {
17 lo = min(xs)
18 hi = max(xs)
19 return lo, hi, sum(xs) / len(xs)
20}
21
22lo, hi, mean = min_max_mean([4.0, 1.0, 7.0, 2.0])
23print(fmt(lo), fmt(hi), fmt(mean))
76def min_max_mean(xs: Arr) {
77 lo = py_bmin(xs)
78 hi = py_bmax(xs)
79 return lo, hi, py_div_f(py_lsum(xs), len(xs))
80}
81lo, hi, mean = min_max_mean([4.0, 1.0, 7.0, 2.0])
82print(fmt(lo), fmt(hi), fmt(mean))
3 a function as an argument
22def apply_twice(f, x):
23 return f(f(x))
24
25def square(x):
26 return x * x
27
28print(apply_twice(square, 3.0))
29print(apply_twice(lambda x: x + 10.0, 1.0))
26def apply_twice(f, x) {
27 return f(f(x))
28}
29
30def square(x) {
31 return x * x
32}
33
34print(fmt(apply_twice(square, 3.0)))
35print(fmt(apply_twice(fn(x) -> x + 10.0, 1.0)))
84def apply_twice(f, x) {
85 return f(f(x))
86}
87def square(x) {
88 return x * x
89}
90print(fmt(apply_twice(square, 3.0)))
91def _lam29(x) {
92 return x + 10.0
93}
94print(fmt(apply_twice(_lam29, 1.0)))
4 a lambda that captures a variable
32scale = 2.5
33scaled = lambda x: scale * x
34print(scaled(4.0))
38scale = 2.5
39scaled = fn(x) -> scale * x
40print(fmt(scaled(4.0)))
96scale = 2.5
97def scaled(x) {
98 return scale * x
99}
100print(fmt(scaled(4.0)))
5 checks
37assert greet("x") == "hello, x!"
38assert apply_twice(square, 2.0) == 16.0
43test "functions" {
44 assert_true(greet("x") == "hello, x!")
45 assert_true(apply_twice(square, 2.0) == 16.0)
46}
102if not (greet("x", "hello") == "hello, x!") {
103 stop("AssertionError")
104}
105if not (apply_twice(square, 2.0) == 16.0) {
106 stop("AssertionError")
107}

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 functions.py

hello, Ada!
hi, Grace!
good morning, Alan!
1.0 7.0 3.5
81.0
21.0
10.0

$ viv run functions.viv

hello, Ada!
hi, Grace!
good morning, Alan!
1.0 7.0 3.5
81.0
21.0
10.0
PASS functions

$ viv run functions.py (py2viv’s translation)

The translation prints exactly what the Python prints.

hello, Ada!
hi, Grace!
good morning, Alan!
1.0 7.0 3.5
81.0
21.0
10.0