【问题标题】:How can I use a user inputted value in my Function in F#如何在 F# 的函数中使用用户输入的值
【发布时间】:2016-09-10 19:49:02
【问题描述】:

我正在尝试在 F# 中创建一个简单的阶乘函数,该函数使用从用户输入的值(使用控制台,我不知道这是否有任何区别)但我似乎找不到任何解决方案能够在我的函数中使用来自用户的值。

    open System

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

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

它经常给我一个错误说“这个表达式应该有类型“int”,但这里有类型“string””。如果有人对如何使其正常工作有任何想法(或者至少可以告诉我需要做什么才能将用户输入的值转换为 INT,那将不胜感激。

【问题讨论】:

    标签: f# user-input factorial


    【解决方案1】:

    F# 不会为您自动转换,因此您需要解析字符串:

    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))
    

    理论上你需要转换回字符串来打印它,但它可以工作,因为 Console.WriteLine 有一个重载,它接受一个整数并进行转换。

    【讨论】:

    • 这不会在运行时爆炸吗?以及somevalue |&gt; int。这会违反 F# 编译安全,告诉您编译期间的危险,而不是让您的应用程序在运行时崩溃。
    • @HMR 当然会在运行时崩溃,我不建议在生产中使用此代码,也不建议最佳实践,只是回答问题。对于生产代码,更好的方法是使用 tryParse 函数,但它需要了解如何处理它,这似乎是一个新手问题。
    • 没什么大不了的。但是如果您编写 F# 代码,请使用 printf formatstring >arg listarg list
    【解决方案2】:

    因为两者:

    somevalue |> int
    

    System.Int32.Parse somevalue
    

    对无效输入抛出异常不是更好地防止您的应用在运行时崩溃吗?

    由于我找不到任何返回 int option 的函数,我写了一个:

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

    (按照 Gustavo 的建议使用 TryParse)

    【讨论】:

      【解决方案3】:

      我的建议是尝试使用 F# 函数,除非没有等效的 F# 函数。

      其次,F# 中的类型转换函数嵌入了System.(type).(Try)Parse。这里的“Try”是可选的,type 是任何数字类型,如int8、...、int64float32 和浮点数。 (最后一个是 64 位的)

      所以int "123" = System.Int32.Parse("123") 是真的。这两个功能是等价的。这也适用于浮点数。

      第三,如果可以的话,尝试使用尾递归:

      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))
      

      如果我们输入4 然后回车,输出将是:

      fact 4 = 24
      

      我不知道在 F# 中是否有任何与ReadLine 等价的东西。我找不到。

      尝试坚持 F# 风格而不是在 C# 和 F# 之间来回切换的原因是其他读者和您自己可能会感到困惑,因为这可能会降低代码的可读性。

      【讨论】:

      • 您声明"Try" is optional。然而,这不一定是真的。例如,int "abc" 会使程序崩溃,而Int32.TryParse("abc") 会更优雅地失败。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-23
      • 2021-03-29
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      • 2020-12-05
      相关资源
      最近更新 更多