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

时间:2015-01-26 01:40:45

标签: f#

我正在写一些非常简单的事情,一个找到int的所有因素的程序。这就是我所拥有的

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

如果我这样做,那么它会弹出一个错误。这个表达式应该有类型单位。但是我尝试将一个表达式打印出来后if..then ..,这假设返回类型单位,但它仍然给出相同的错误。我对此感到很失落。有人可以帮忙吗?感谢

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

=是比较,而非作业。你想要

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

但请注意,这两个解决方案都非常单一,因为这个问题同样容易解决。