我正在写一些非常简单的东西,一个可以找到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
。结果包括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
=
是比较,而不是赋值。你想要任何一个
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
但是请注意,这两种解决方案都是非常不合时宜的,因为对于此问题,同样容易的不可变解决方案。