Compare
Python and Viv, side by side
39 small programs, each written twice, once in Python and once in Viv. The two versions use the same algorithm, print the same output, and are cut into the same regions, so a page can show them line against line. The notes on each page list the differences in syntax to look for.
A script, study/compare/check.sh, runs every pair: the Python with CPython and NumPy,
the Viv in the interpreter, compiled to C and compiled to wasm. It fails unless the outputs match. Where
a pair's output differs, its notes name the lines and why, and the rest of the output must still match.
Each page also shows what py2viv,
the translator from numeric Python, makes of the Python, or its reason for refusing it.
Basics
Printing and formatting, variables and arithmetic, conditionals, loops, functions.
- Printing and formatting same output
- Arithmetic and conditionals output differs
- Loops same output
- Functions same output
Strings
Split, join, format, and text processed character by character.
- String basics same output
- Word count same output
- Palindromes same output
- Caesar cipher same output
- Numbers from text same output
Lists and growable arrays
Building a list as you go, filtering, sorting, slicing.
- Growing a list same output
- Sorting same output
- Slices, copies and aliases output differs
Dicts and maps
Counting with string keys and number keys.
- Word frequency same output
- Counting with number keys same output
Records, classes and tuples
Dataclasses against records; several results and unpacking.
- Records and dataclasses same output
- Tuples and unpacking same output
- A class with state same output
Recursion
Factorial, memoized Fibonacci, the Tower of Hanoi, merge sort, quicksort.
- Factorial same output
- Fibonacci with a memo same output
- Tower of Hanoi same output
- Merge sort same output
- Quicksort in place same output
Files
Writing text and reading it back line by line.
- Reading and writing text files same output
Numerics
Root finding, quadrature, ODEs, iterative and direct linear algebra: NumPy against Viv's arrays.
- Newton's method same output
- Bisection same output
- Simpson's rule same output
- Runge-Kutta 4 on an oscillator same output
- Euler against the exact solution same output
- Jacobi iteration same output
- Power iteration same output
- LU factorization and solve same output
- Matrix operations same output
Random numbers
A seeded generator whose draws match NumPy's.
- Seeded random numbers same output
Gradients
A gradient derived by hand in Python against Viv's grad.
- Gradients by hand and by grad same output
Plotting
Matplotlib against Viv's figure records.
- A line plot output differs
A small GPT
A transformer trained with a hand-written backward pass: NumPy classes, then PyTorch, against lib/gpt.
- A small GPT in NumPy and in Viv same output
- The same GPT in PyTorch, against Viv same output
Errors
Exceptions against checked results and stop.
- Exceptions against checked results same output
Tests
Test functions and asserts against Viv's test blocks.
- Tests same output
The differences to learn first
- A bare float prints with six significant digits (
fmt(x)gives Python’s digits);printputs a space between its arguments, as Python’s does. Printing and formatting - A number is a double unless declared
Int; power is^;roundtakes a tie away from zero, soround(2.5)is 3; booleans print astrueandfalse. Arithmetic and conditionals - No default or keyword arguments; a lambda is
fn(x) -> expr. Functions -
for i to n,for i from a to b by s,for i to n reversed; braces, not indentation. Loops -
a.append(x)isa = append(a, x); comprehensions,inand negative indices read as in Python;for row in rows(table)walks a matrix. Growing a list - A slice of an array is a copy, where a NumPy slice is a view. Slices, copies and aliases
-
sort(a)sorts in place and returns nothing;sorted(xs, key=f)takes numbers or strings as keys, not tuples. Sorting - A dict is
map();get(m, k, d)andremove(m, k)are functions, andk in mreads as in Python. Word frequency - A record is a value:
r.f = vchanges the variable’s own record, never another name’s;T { f: v, ..old }builds a changed copy. A class with state - No
globalstatement: a function cannot assign a global number, only write into a global array or map. Fibonacci with a memo - No exceptions: a function returns a flag with its result, and
stop("...")ends the run. Exceptions against checked results -
test "name" { ... }blocks run where they stand and printPASSorFAIL. Tests
Where the outputs differ
- Arithmetic and conditionals: Two lines print differently and are left out of the comparison. Python's round(2.5) is 2, because Python rounds a tie to the even neighbor; Viv's round(2.5) is 3, because Viv rounds a tie away from zero. Python prints a boolean as True or False, and Viv prints it as true or false.
- Slices, copies and aliases: 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.
- A line plot: Matplotlib writes a PNG and the Python side prints that it saved it; Viv prints the figure as text records (figure, plot, style, scatter), which a page, a notebook or
viv plotdraws. Those lines are left out of the comparison; the peaks line is compared.