I found a project that aims to implement a CLI calculator app in as many different languages and ways as possible. Having a little experience in PS, I tried my hand at it. The requirements are as follows:

- Use a set interface (that is correctly done here)
- Must use functions
- No builtins, unless it’s to interact with the terminal
- Must have comments
- Mustn’t throw an error on input or keyboard interrupt

I don’t have an idea about PS best practices, so I’m hoping for some input there. Anyways, here’s what I came up with:

```
# Ask the user to input a number using the given prompt string
function Get-Double {
param (
$Prompt
)
do {
$inp = Read-Host -Prompt $Prompt
# Try to cast, if that fails $num will contain null
$num = $inp -as (Double)
$ok = $num -ne $NULL
if (-not $ok) {
Write-Host "You must enter a numeric value" -ForegroundColor Red
}
# try until the user gets it right
} until ($ok)
return $num
}
# Do a exponentiation using the given base and exponent
function Calculate-Exponent {
param (
$Base,
$Exp
)
$res = $base
for ($i = 1; $i -lt $exp; $i++) {
$res *= $exp
}
return $res
}
while (1) {
clear
Write-Host "PowerShell CLI calc v1.0" -ForegroundColor Yellow
Write-Host "Choose a function"
Write-Host "1 - Add 3 - Multiply 5 - Exponentiation"
Write-Host "2 - Subtract 4 - Divide"
do {
# The Read-Host cmdlet puts a ":" after the supplied prompt when using -Prompt.
# If we do it like this, we can get the requested custom prompt without that
Write-Host -nonewline ">>> "
$mode = Read-Host
#match a single 1 2 3 4 or 5
$ok = $mode -match "^(1-5)$"
if (-not $ok) {
Write-Host "Please enter a number between 1 and 5" -ForegroundColor Red
}
} until ($ok)
# Newline for formatting
Write-Host ""
# Array definitions so that we can use the inputted mode value easily
$modes = @("Addition", "Subtraction", "Multiplication", "Division", "Exponentation")
$signs = @("+", "-", "*", "/", "^")
Write-Host $("{0} - Please choose two numbers a and b to calculate a {1} b" -f $modes($mode-1), $signs($mode-1))
$a = Get-Double -Prompt "a"
$b = Get-Double -Prompt "b"
switch ($mode) {
1 {$res = $a + $b; break}
2 {$res = $a - $b; break}
3 {$res = $a * $b; break}
4 {$res = $a / $b; break}
5 {$res = Calculate-Exponent -Base $a -Exp $b; break}
}
Write-Host $("Result: {0} {1} {2} = {3}" -f $a, $signs($mode-1), $b, $res)
Write-Host ""
Write-Host "Type Q/q to quit or press Enter to restart"
do {
Write-Host -NoNewline ">>> "
$inp = $NULL
$inp = Read-Host
# Match a single q or Q
if ($inp -match "^(qQ)$") {
exit;
}
# Pressing enter results in the input being of length 0
$ok = $inp.Length -eq 0
if (-not $ok) {
Write-Host "Please type either Q/q to quit or press Enter to restart!" -ForegroundColor Red
}
} until($ok);
}
```
```