Guide
Filters: stdin, stderr, exit codes
Since Sprints 347–348 a POLYTONE program is a real command-line filter.
fn grades(input: Stdin) -> Result[List[Text], Text]:
mut out: List[Text] = []
for line in input.lines():
let parts = line.split(" ")
if parts.len() != 2:
return Err("not 'name points': {line}")
match parts[1].to_int():
case Some(p):
out.push("{parts[0]} {if_pass(p)}")
case None:
return Err("not a number: {parts[1]}")
return Ok(out)
fn if_pass(points: Int) -> Text:
if points >= 50:
return "pass"
return "fail"
fn main(input: Stdin) -> Result[Int, Text]:
let lines = grades(input)?
for line in lines:
print(line)
eprint("{lines.len()} graded")
return Ok(0)
test "a mocked stdin grades":
assert grades(mock_stdin("ada 92\nbob 31\n")) == Ok(["ada pass", "bob fail"])
assert grades(mock_stdin("oops\n")) == Err("not 'name points': oops")$ ptc test grade.pt
Recorded output of the real compiler
main receives its standard input as a Stdin capability — read whole once, so lines() and read_all() see the same text — and returns Void, an Int exit code, or a Result: an Err exits 1 with its text on stderr, so the ? in main ends the tool like Rust's main does. eprint writes stderr, never stdout. Under ptc run, `printf 'ada 92\n' | ptc run grade.pt` prints `ada pass`, reports `1 graded` on stderr and exits 0.