我正在写一些非常简单的事情,一个找到int的所有因素的程序。这就是我所拥有的
let factor n=
let ls=[]
for i=1 to n do
if i % n =0 then ls = i::ls
l
如果我这样做,那么它会弹出一个错误。这个表达式应该有类型单位。但是我尝试将一个表达式打印出来后if..then ..,这假设返回类型单位,但它仍然给出相同的错误。我对此感到很失落。有人可以帮忙吗?感谢
答案 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
。结果包括1
和n
。这可以通过更改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
但请注意,这两个解决方案都非常单一,因为这个问题同样容易解决。