You will use
pooka/file:file.readreturnsResult(String, FileError)pooka/string:lowercase,replace,splitpooka/dict:dict.emptyand theupsertmethodpooka/list:fold,filter,sort_by,take,each
The whole program
module main
import pooka/dict.{Dict}
import pooka/file
import pooka/int
import pooka/io
import pooka/list
import pooka/string
count(words: List(String)) -> Dict(String, Int) {
list.fold(words, dict.empty(), fn(counts: Dict(String, Int), word: String) {
counts.upsert(word, fn(seen: Option(Int)) {
match seen {
Some(n) -> n + 1
None -> 1
}
})
})
}
main() {
match file.read("poem.txt") {
Ok(text) -> {
let words = text
|> string.lowercase
|> string.replace("\n", " ")
|> string.split(" ")
|> list.filter(fn(w: String) { w != "" })
count(words).to_list()
|> list.sort_by(fn(a: #(String, Int), b: #(String, Int)) {
int.compare(b.1, a.1)
})
|> list.take(3)
|> list.each(fn(pair: #(String, Int)) {
let _ = io.println(pair.0 + ": " + int.to_string(pair.1))
Nil
})
}
Error(problem) -> {
let _ = io.eprintln(
"Could not read " + problem.path + ": " + problem.message
)
Nil
}
}
}
Run it
Put a few lines in poem.txt next to pooka.toml and run it:
printf 'the owl and the moon\nthe lamp and the owl\nthe end\n' > poem.txt
pooka run
the: 5
and: 2
owl: 2
How it works
- Read the file.
file.readnever throws: a missing file comes back asError(FileError), carrying the path and a message. Thematchmakes both outcomes explicit. - Make words. Lowercase the text so “The” and “the” count together, turn newlines into spaces, split on spaces, and drop the empty strings left by double spaces.
- Tally.
countfolds over the words with aDict(String, Int).upserthands you the current count as anOption:Nonethe first time,Some(n)after. - Rank and print. Turn the dict into pairs, sort by the count (
b.1beforea.1for descending order), take three and print each.io.printlnreturns aResult, so it's discarded withlet _ =.
Try next: read the file name from env.args() instead of hard-coding poem.txt, or strip punctuation with a few more string.replace calls.