Arithmetic
A Roc program which accepts two integers from the command line and prints their sum, difference, product, quotient, remainder, and exponentiation.
Code
app [main!] { cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br" } import cli.Stdout import cli.Arg exposing [Arg] main! : List Arg.Arg => Result {} _ main! = |raw_args| args : { a : I32, b : I32 } args = read_args(raw_args)? result = [ ("sum", args.a + args.b), ("difference", args.a - args.b), ("product", args.a * args.b), ("integer quotient", args.a // args.b), ("remainder", args.a % args.b), ("exponentiation", Num.pow_int(args.a, args.b)), ] |> List.map( |(operation, answer)| "${operation}: ${Num.to_str(answer)}", ) |> Str.join_with("\n") Stdout.line!(result) ## Reads two command-line arguments, attempts to parse them as `I32` numbers, ## and returns a [`Result`](https://www.roc-lang.org/builtins/Result). ## ## On success, the [`Result`](https://www.roc-lang.org/builtins/Result) ## will contain a record with two fields, `a` and `b`, holding the parsed `I32` values. ## ## This will fail if an argument is missing, if there's an issue with parsing ## the arguments as `I32` numbers, or if the parsed numbers are outside the ## expected range (-1000 to 1000). Then the [`Result`](https://www.roc-lang.org/builtins/Result) will contain ## an `Exit I32 Str` error. read_args : List Arg -> Result { a : I32, b : I32 } [Exit I32 Str] read_args = |raw_args| arg_range_min = -1000 arg_range_max = 1000 expected_nr_of_args = 2 + 1 # +1 because first will be name or path of the program arg_range_min_str = Inspect.to_str(arg_range_min) arg_range_max_str = Inspect.to_str(arg_range_max) # TODO this function should not use Exit for modularity. Only perform this change after static dispatch has landed! invalid_args = Exit(1, "Error: Please provide two integers between ${arg_range_min_str} and ${arg_range_max_str} as arguments.") invalid_num_str = Exit(1, "Error: Invalid number format. Please provide integers between ${arg_range_min_str} and ${arg_range_max_str}.") args = if List.len(raw_args) != expected_nr_of_args then return Err(invalid_args) else List.map(raw_args, Arg.display) a_result = List.get(args, 1) |> Result.try(Str.to_i32) b_result = List.get(args, 2) |> Result.try(Str.to_i32) when (a_result, b_result) is (Ok(a), Ok(b)) -> if a < arg_range_min or a > arg_range_max or b < arg_range_min or b > arg_range_max then Err(invalid_num_str) else Ok({ a, b }) _ -> Err(invalid_num_str)
Output
Run this from the directory that has main.roc
in it:
$ roc main.roc -- 20 4 sum: 24 difference: 16 product: 80 integer quotient: 5 remainder: 0 exponentiation: 160000