Python and Viv · Strings
String basics
What to notice
- The string methods are Python's, with Python's names and results:
strip,upper,split,find,replace,count,startswith.t.upper()in Viv is the callupper(t); any function can be called with a dot this way. joinis the exception to the dot form: Python's"-".join(words)is Viv'sjoin("-", words), the separator first.- Indices and slices count characters as Python's do, including negative indices and a step of -1 (
t[::-1]). Arrays of numbers take negative indices too; their slice step must be 1 or more. print(words)writes a list of strings the way Python does,['The', 'quick', 'brown', 'fox'].- f-string alignment (
{w:<8},{w:>8},{w:^8}) works for strings in both. intests for a substring in both languages.
Python text_basics.py · 37 lines
Viv text_basics.viv · 44 lines
py2viv translated from text_basics.py
What py2viv adds before the program
(nothing)
(nothing)
15 lines: a header and the guard functions its translation calls
1###
2Translated from text_basics.py by py2viv 0.2.0 (numeric Python -> Viv).
3Python source sha256: 1e859bab2702cf88eeee384bd4384237d18de5ad7a5f5a50062bed5c8c7a316f
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#| An int result, as Python's int: a -0.0 becomes 0 (an int has no sign on zero), and the run
9#| stops at 2^53, past which a double no longer holds every integer (Python's int does).
10def py_int(x) {
11 if abs(x) >= 9007199254740992 {
12 stop("py2viv: an integer reached 2^53; Python's int is exact there and a double is not")
13 }
14 return x + 0.0
15}
1 a string and its pieces
4s = " The quick brown fox "
5t = s.strip()
6print(f"[{t}] has {len(t)} characters")
7print(t.upper())
8print(t.lower())
9print(t[4:9], t[-3:], t[::-1])
2s = " The quick brown fox "
3t = s.strip()
4print(f"[{t}] has {len(t):d} characters")
5print(t.upper())
6print(t.lower())
7print(t[4:9], t[-3:], t[::-1])
20s = " The quick brown fox "
21t = strip(s)
22print("[", t, "] has ", fmt((len(t)) + 0.0, "d"), " characters", sep="")
23print(upper(t))
24print(lower(t))
25print(t[4:9], t[-3:], t[::-1])
2 split and join
12words = t.split()
13print(words)
14print("-".join(words))
15print("a,b,,c".split(","))
10words = t.split()
11print(words)
12print(join("-", words))
13print("a,b,,c".split(","))
27words = split(t)
28print(words)
29print(join("-", words))
30print(split("a,b,,c", ","))
3 search and replace
18print(t.find("quick"), t.find("slow"))
19if t.startswith("The") and t.endswith("fox"):
20 print("starts with The, ends with fox")
21print(t.replace("quick", "slow"))
22print(t.count("o"))
16print(t.find("quick"), t.find("slow"))
17if t.startswith("The") and t.endswith("fox") {
18 print("starts with The, ends with fox")
19}
20print(t.replace("quick", "slow"))
21print(t.count("o"))
32print(fmt((find(t, "quick")) + 0.0, "d"), fmt((find(t, "slow")) + 0.0, "d"))
33if startswith(t, "The") and endswith(t, "fox") {
34 print("starts with The, ends with fox")
35}
36print(replace(t, "quick", "slow"))
37print(fmt((count(t, "o")) + 0.0, "d"))
4 padding and alignment
25for w in words:
26 print(f"|{w:<8}|{w:>8}|{w:^8}|")
24for w in words {
25 print(f"|{w:<8}|{w:>8}|{w:^8}|")
26}
39for py_i1 to len(words) {
40 w = words[py_i1]
41 print("|", fmt(w, "<8"), "|", fmt(w, ">8"), "|", fmt(w, "^8"), "|", sep="")
42}
5 characters one at a time
29vowels = 0
30for c in t:
31 if c.lower() in "aeiou":
32 vowels += 1
33print("vowels:", vowels)
29vowels = 0
30for c in t {
31 if c.lower() in "aeiou" {
32 vowels += 1
33 }
34}
35print("vowels:", vowels)
44vowels = 0
45for py_i2 to len(t) {
46 c = t[py_i2]
47 if lower(c) in "aeiou" {
48 vowels = py_int(vowels + 1)
49 }
50}
51print("vowels:", fmt(vowels + 0.0, "d"))
6 checks
36assert "fox" in t
37assert t.split(" ")[1] == "quick"
38test "strings" {
39 assert_true("fox" in t)
40 assert_true(t.split(" ")[1] == "quick")
41}
53if not ("fox" in t) {
54 stop("AssertionError")
55}
56if not (split(t, " ")[1] == "quick") {
57 stop("AssertionError")
58}
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 text_basics.py
[The quick brown fox] has 19 charactersTHE QUICK BROWN FOXthe quick brown foxquick fox xof nworb kciuq ehT['The', 'quick', 'brown', 'fox']The-quick-brown-fox['a', 'b', '', 'c']4 -1starts with The, ends with foxThe slow brown fox2|The | The| The ||quick | quick| quick ||brown | brown| brown ||fox | fox| fox |vowels: 5
$ viv run text_basics.viv
[The quick brown fox] has 19 charactersTHE QUICK BROWN FOXthe quick brown foxquick fox xof nworb kciuq ehT['The', 'quick', 'brown', 'fox']The-quick-brown-fox['a', 'b', '', 'c']4 -1starts with The, ends with foxThe slow brown fox2|The | The| The ||quick | quick| quick ||brown | brown| brown ||fox | fox| fox |vowels: 5PASS strings
$ viv run text_basics.py (py2viv’s translation)
The translation prints exactly what the Python prints.
[The quick brown fox] has 19 charactersTHE QUICK BROWN FOXthe quick brown foxquick fox xof nworb kciuq ehT['The', 'quick', 'brown', 'fox']The-quick-brown-fox['a', 'b', '', 'c']4 -1starts with The, ends with foxThe slow brown fox2|The | The| The ||quick | quick| quick ||brown | brown| brown ||fox | fox| fox |vowels: 5