How can I use a user inputted value in my Function

2019-01-20 04:24发布

问题:

So I'm trying to make a simple factorial function in F# that uses a value inputted from the user (using the console, I don't know if that makes any difference) but I can't seem to find any solution to be able to use the value from the user in my function.

    open System

    let rec fact x =
        if x < 1 then 1
        else x * fact (x - 1)

    let input = Console.ReadLine()
    Console.WriteLine(fact input)

It constantly gives me the error saying "This expression was expected to have type "int" but here has type "string"". If anyone has any idea on how to make it work properly (or at least can tell me what I need to do to convert my user inputted value into an INT, that would be greatly appreciated.

Thank you for any help.

回答1:

F# does no automatic conversions for you, so you'll need to parse the string:

open System

let rec fact x =
    if x < 1 then 1
    else x * fact (x - 1)

let input = Console.ReadLine()
Console.WriteLine(fact (Int32.Parse input))

In theory you would need to convert back to string to print it, but it works because there is an overload for Console.WriteLine that takes an integer and does the conversion.



回答2:

Since both:

somevalue |> int

and

System.Int32.Parse somevalue

Throw an exception on invalid input is it not better to prevent your app from blowing up at runtime?

Since I could not find any function that returns int option I wrote one:

let asInt32 numberString =
  let (success,num)  = 
    System.Int32.TryParse(numberString)
  if success then
    Some num
  else
    None
asInt32 "22"

(using TryParse as Gustavo suggested)



回答3:

First of all USE printf or printfn to write to console. Sry but if you code in F# and use C# functions, code in C# then. Unless there isn't an equivalent F# function use F# functions. Second of all the type cast functions in F# has System.(type).(Try)Parse embedded in them. Try here is optional, and type is any number type like int8, ..., in64 and float32 and float. (last on are 64 bit)

So int "123" = System.Int32.Parse("123") are true. the two functions are equivalent this goes for floating point numbers too.

Third if you can use tail recursion

let fact n =
  let rec help acc = function
    | n when n <= 0 -> acc
    | n             -> help (acc*n) (n-1)
  help 1 n

let input = System.Console.ReadLine()
printfn "fact %s = %d" input (fact (int input))

if we type 4 and then press enter the output would be

fact 4 = 24

I don't know if there is any equivalent to ReadLine in F#, couldn't find any. the reason to keep inside the F# style and not jump around are because other readers and yourself will get confused, it makes the code less readable.