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

Exceptions against checked results

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 checked.py · 42 lines
Viv checked.viv · 65 lines
py2viv refuses checked.py
1 a function that can fail
4def parse_age(text):
5 value = int(text)
6 if value < 0:
7 raise ValueError(f"age cannot be negative: {value}")
8 return value
2def parse_age(text) {
3 body = text
4 if text.startswith("-") {
5 body = text[1:]
6 }
7 if not body.isdigit() {
8 return false, 0, f"invalid literal for int() with base 10: {text!r}"
9 }
10 value = int(text)
11 if value < 0 {
12 return false, 0, f"age cannot be negative: {value:d}"
13 }
14 return true, value, ""
15}
py2viv refuses this program:
checked.py:12:5: not numeric Python: `try`/`except`
        try:
        ^^^^
  Check the condition and stop with `assert`.
checked.py:20:5: not numeric Python: `try`/`except`
        try:
        ^^^^
  Check the condition and stop with `assert`.
checked.py:25:7: not numeric Python: printing a value of unknown type (it comes from a construct refused elsewhere)
    print(ratio(1.0, 4.0), ratio(1.0, 0.0))
          ^^^^^^^^^^^^^^^
  Fix the refusal that produced it.
checked.py:30:5: not numeric Python: `try`/`except`
        try:
        ^^^^
  Check the condition and stop with `assert`.
checked.py:36:13: not numeric Python: d.values() outside a for loop header
    total = sum(stock.values())
                ^^^^^^^^^^^^^^
  Loop over it: `for k, v in d.items():` (unrolled per key).
5 constructs outside the numeric subset (tools/py2viv/SUBSET.md)
2 the caller handles the failure
11for text in ["42", "-3", "abc", "7"]:
12 try:
13 age = parse_age(text)
14 print(f"{text!r}: age {age}")
15 except ValueError as e:
16 print(f"{text!r}: refused ({e})")
18for text in ["42", "-3", "abc", "7"] {
19 ok, age, why = parse_age(text)
20 if ok {
21 print(f"{text!r}: age {age:d}")
22 }
23 else {
24 print(f"{text!r}: refused ({why})")
25 }
26}
(refused)
3 division by zero
19def ratio(a, b):
20 try:
21 return a / b
22 except ZeroDivisionError:
23 return float("nan")
24
25print(ratio(1.0, 4.0), ratio(1.0, 0.0))
29def ratio(a, b) {
30 if b == 0 {
31 return float("nan")
32 }
33 return a / b
34}
35
36print(fmt(ratio(1.0, 4.0)), fmt(ratio(1.0, 0.0)))
(refused)
4 a missing key
28stock = {"apple": 3, "pear": 0}
29for item in ["apple", "plum"]:
30 try:
31 print(item, stock[item])
32 except KeyError:
33 print(item, "not stocked")
39stock = map()
40stock["apple"] = 3
41stock["pear"] = 0
42for item in ["apple", "plum"] {
43 if item in stock {
44 print(item, stock[item])
45 }
46 else {
47 print(item, "not stocked")
48 }
49}
(refused)
5 a check that should never fail
36total = sum(stock.values())
37if total != 3:
38 raise RuntimeError(f"stock total is {total}, expected 3")
39print("stock total checked")
52total = sum(values(stock))
53if total != 3 {
54 stop(f"stock total is {total:d}, expected 3")
55}
56print("stock total checked")
(refused)
6 checks
42assert parse_age("42") == 42
59test "parse" {
60 ok, age, why = parse_age("42")
61 assert_true(ok and age == 42)
62}
(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 checked.py

'42': age 42
'-3': refused (age cannot be negative: -3)
'abc': refused (invalid literal for int() with base 10: 'abc')
'7': age 7
0.25 nan
apple 3
plum not stocked
stock total checked

$ viv run checked.viv

'42': age 42
'-3': refused (age cannot be negative: -3)
'abc': refused (invalid literal for int() with base 10: 'abc')
'7': age 7
0.25 nan
apple 3
plum not stocked
stock total checked
PASS parse