Sorry if my title isn't descriptive enough, I wasn't sure how to phrase the problem... I'm used to programming in C# and have been dabbling in F#. I'm trying to write a function I use in some C# scripts that checks if the string is numeric. I have a F# function written up like this though its not correct according to VS because its expecting an else:
let IsNumeric (entry : string) : bool = // Function to make sure the data entered is numeric
for c : char in entry do
if not ((c >= '0') && (c <= '9')) then
false
true
If I put in an else statement and remove the true at the bottom:
let IsNumeric (entry : string) : bool = // Function to make sure the data entered is numeric
for c : char in entry do
if not ((c >= '0') && (c <= '9')) then
false
else true
I get this error
FS0001 This expression was expected to have type 'bool' but here has type 'unit'
... if I keep the true at the bottom like in the first code block I get a warning about it returning a bool but should be ignored which I don't quite understand.
FS0020 The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.
This is the C# method I wrote that I've been trying to adapt:
public static bool IsNumeric(string s) //this just makes sure the string is numeric.
{
foreach (char c in s)
{
if (!(c >= '0' && c <= '9') && c != '.' && c != '-')
{
return false;
}
}
return true;
}
How should I approach this?
F# as most functional languages doesn't support early return. Last evaluated expression is return value.
Canonical solution would be to use recursive function, which compiles to simple loop if you do it right.
let isNumeric (str: string) : bool =
let rec loop index =
if index >= str.Length then
true
else
let c = str.[index]
if (c >= '0' && c <= '9') || c = '.' || c = '-' then
loop (index + 1)
else false
loop 0
You can check what it compiles to with ILSpy, ILDasm or SharpLab
Most F#-ish is to use
let isNumeric str =
String.forall (fun c -> (c >= '0' && c <= '9') || c = '.' || c = '-') str
And most correct is to use, because you don't check correctness and ..-
would be correct number
let isNumeric (str: string) = System.Double.TryParse str |> fst