赋值:此表达式应具有类型单位

  • 本文关键字:类型 单位 表达式 赋值 f#
  • 更新时间 :
  • 英文 :


我正在写一些非常简单的东西,一个可以找到int的所有因素的程序。这是我所拥有的

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

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

您正在尝试将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

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

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

但是请注意,这两种解决方案都是非常不合时宜的,因为对于此问题,同样容易的不可变解决方案。

最新更新