Python and Viv · Strings
Word count
What to notice
splitlines,split,stripwith a set of characters, andlowerare the same calls, and"\n".join(LINES)isjoin("\n", LINES).- A trailing comma after the last element of an array literal is allowed in both.
[clean(w) for w in words],max(cleaned, key=len)andenumerate(lines, start=1)are the same in both.- A number in a Viv f-string is written as
strwrites a float (1.0), so the Viv side asks for{n:d}where Python's int prints1.
Python word_count.py · 33 lines
Viv word_count.viv · 38 lines
py2viv refuses word_count.py
1 the text
4LINES = [
5 "It was the best of times, it was the worst of times,",
6 "it was the age of wisdom, it was the age of foolishness,",
7 "it was the epoch of belief, it was the epoch of incredulity.",
8]
9TEXT = "\n".join(LINES)
2LINES = [
3 "It was the best of times, it was the worst of times,",
4 "it was the age of wisdom, it was the age of foolishness,",
5 "it was the epoch of belief, it was the epoch of incredulity."
6]
7TEXT = join("\n", LINES)
py2viv refuses this program:
word_count.py:24:15: not numeric Python: max of a string
longest = max(cleaned, key=len)
^^^^^^^
Python compares numbers (and, with a key, returns the item itself); pass numbers.
word_count.py:25:19: not numeric Python: printing a value of unknown type (it comes from a construct refused elsewhere)
print("longest:", longest, len(longest))
^^^^^^^
Fix the refusal that produced it.
2 constructs outside the numeric subset (tools/py2viv/SUBSET.md) 2 lines, words and characters
12lines = TEXT.splitlines()
13words = TEXT.split()
14print(len(lines), "lines,", len(words), "words,", len(TEXT), "characters")
10lines = TEXT.splitlines()
11words = TEXT.split()
12print(len(lines), "lines,", len(words), "words,", len(TEXT), "characters")
(refused)
3 clean each word
17def clean(word):
18 return word.strip(".,;:!?").lower()
19
20cleaned = [clean(w) for w in words]
21print(cleaned[:6])
15def clean(word) {
16 return word.strip(".,;:!?").lower()
17}
18
19cleaned = [clean(w) for w in words]
20print(cleaned[:6])
(refused)
4 the longest word
24longest = max(cleaned, key=len)
25print("longest:", longest, len(longest))
23longest = max(cleaned, key=len)
24print("longest:", longest, len(longest))
(refused)
5 words per line
28for n, line in enumerate(lines, start=1):
29 print(f"line {n}: {len(line.split())} words")
27for n, line in enumerate(lines, start=1) {
28 print(f"line {n:d}: {len(line.split()):d} words")
29}
(refused)
6 checks
32assert cleaned.count("was") == 6
33assert longest == "foolishness"
32test "word count" {
33 assert_true(cleaned.count("was") == 6)
34 assert_true(longest == "foolishness")
35}
(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 word_count.py
3 lines, 36 words, 170 characters['it', 'was', 'the', 'best', 'of', 'times']longest: foolishness 11line 1: 12 wordsline 2: 12 wordsline 3: 12 words
$ viv run word_count.viv
3 lines, 36 words, 170 characters['it', 'was', 'the', 'best', 'of', 'times']longest: foolishness 11line 1: 12 wordsline 2: 12 wordsline 3: 12 wordsPASS word count