赋值:这个表达式应该有类型 unit
Assignment: this expression was expected to have the type unit
我正在写一些非常简单的东西,一个找到 int 的所有因子的程序。这是我的
let factor n=
let ls=[]
for i=1 to n do
if i % n =0 then ls = i::ls
l
如果我这样做,它会弹出一个错误 This expression was expected to have the type unit。但我试图在 if..then.. 之后放置一个打印内容的表达式,假设为 return 类型单元,但它仍然给出相同的错误。我对此迷路了。有人可以帮忙吗?谢谢
=
是比较,不是赋值。你想要
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
但是请注意,这两种解决方案都非常单一,因为对于这个问题有同样简单的不可变解决方案。
您正试图将 ls
变成一个可变变量并用 =
赋值给它。虽然这是可能的,但通过使用 mutable
(1) or 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
,后者将给定的谓词(在行尾)应用于 select 上的除数 n
。但是,如果 n
很大,临时列表将变得非常大。我们可以使用惰性评估序列来代替,这不会影响内存使用:
let factor n =
{1..n} |> Seq.filter (fun x -> n % x = 0) |> Seq.toList
这里我们过滤 'lazy' 序列,只将(小得多的)结果序列转换为末尾的列表:
> factor 10000000;;
val it : int list =
[1; 2; 4; 5; 8; 10; 16; 20; 25; 32; ... etc
我正在写一些非常简单的东西,一个找到 int 的所有因子的程序。这是我的
let factor n=
let ls=[]
for i=1 to n do
if i % n =0 then ls = i::ls
l
如果我这样做,它会弹出一个错误 This expression was expected to have the type unit。但我试图在 if..then.. 之后放置一个打印内容的表达式,假设为 return 类型单元,但它仍然给出相同的错误。我对此迷路了。有人可以帮忙吗?谢谢
=
是比较,不是赋值。你想要
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
但是请注意,这两种解决方案都非常单一,因为对于这个问题有同样简单的不可变解决方案。
您正试图将 ls
变成一个可变变量并用 =
赋值给它。虽然这是可能的,但通过使用 mutable
(1) or 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
,后者将给定的谓词(在行尾)应用于 select 上的除数 n
。但是,如果 n
很大,临时列表将变得非常大。我们可以使用惰性评估序列来代替,这不会影响内存使用:
let factor n =
{1..n} |> Seq.filter (fun x -> n % x = 0) |> Seq.toList
这里我们过滤 'lazy' 序列,只将(小得多的)结果序列转换为末尾的列表:
> factor 10000000;;
val it : int list =
[1; 2; 4; 5; 8; 10; 16; 20; 25; 32; ... etc