【问题标题】:Assignment: this expression was expected to have the type unit赋值:这个表达式应该有单位类型
【发布时间】:2015-01-26 01:40:44
【问题描述】:

我正在编写一些非常简单的东西,一个查找 int 的所有因子的程序。这是我所拥有的

let factor n=
  let ls=[]
  for i=1 to n do
    if i % n =0 then ls = i::ls
  l

如果我这样做,那么它会弹出一个错误这个表达式应该有类型单元。但是我尝试在 if..then.. 之后放置一个打印某些内容的表达式,假设返回类型单位,但它仍然给出相同的错误。我对此感到迷茫。有人可以帮忙吗?谢谢

【问题讨论】:

    标签: f#


    【解决方案1】:

    您正试图将ls 变成一个可变变量并用= 分配它。虽然这是可能的,但通过使用 mutable (1)ref (2) 以及 <-:= 赋值运算符,这在函数世界中通常是不鼓励的。
    朴素算法的一个可能更惯用的实现可能是:

    let factor n =
        let rec factorLoop curr divs =
            if curr > n then divs
            else
                if n % curr = 0
                then factorLoop (curr+1) (curr::divs)
                else factorLoop (curr+1) divs
        factorLoop 1 [] |> List.rev
    
    > factor 12;;
    val it : int list = [1; 2; 3; 4; 6; 12]
    

    这里的 main 函数定义了一个递归的内部 factorLoop 函数。递归是我们可以避免在函数式语言中多次使用可变变量的方式。递归内部函数沿着作为当前要测试的除数的curr 变量和当前找到的除数的列表divs 线程。结果包括1n。这可以通过改变curr的初始值和factorLoop第一行的终止条件来分别改变。

    值得注意的是,可以通过使用 F# 库将其全部缩小到一行:

    let factor n =
        [1..n] |> List.filter (fun x -> n % x = 0)
    

    在这里,我们构建了一个值列表1..n,并将它们提供给List.filter,它应用给定的谓词(在行尾)仅选择n 上的除数。但是,如果n 很大,则临时列表将变得非常大。我们可以改用惰性求值序列,这不会破坏内存使用:

    let factor n =
        {1..n} |> Seq.filter (fun x -> n % x = 0) |> Seq.toList
    

    这里我们过滤一个“惰性”序列,并且只将(小得多的)结果序列转换为最后的列表:

    > factor 10000000;;
    val it : int list =
      [1; 2; 4; 5; 8; 10; 16; 20; 25; 32; ... etc
    

    【讨论】:

      【解决方案2】:

      = 是比较,而不是赋值。你想要一个

      let factor n =
          let mutable ls = []
          for i = 1 to n do
              if n % i = 0 then ls <- i::ls
          ls
      

      let factor n =
          let ls = ref []
          for i = 1 to n do
              if n % i = 0 then ls := i::(!ls)
          !ls
      

      但是请注意,这两种解决方案都非常单一,因为对于这个问题也有同样简单的不可变解决方案。

      【讨论】:

      • 我要补充一点,这些函数并不能解决问题,它们相当于let factor n = [if n &gt;= 0 then yield n]。在问题和这个答案中,模计算都是错误的。
      • @Vandroiy :这个答案是对实际提出的问题的回应,即关于语法错误的问题。 OP没有要求一种有效的方法来分解一个数字。 ;-]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-26
      相关资源
      最近更新 更多