为什么简单的局限于整数范围循环表达式?(Why are simple for loop expres

2019-08-31 08:06发布

根据F#的规格(见§6.5.7 ),for循环简单的通过整数界( int又名int32又名System.Int32 )限制startstop ,如

for i = start to stop do
    // do sth.

我不知道为什么需要这种类型的for循环迭代边界是int32 。 为什么不允许uint32int64bigint

我知道该序列迭代表达式( for ... in ... )可以遍历任意序列; 然而,这需要分配一个迭代,并调用MoveNextCurrent并没有什么,因此可以大大低效率比普通的循环可能是(增量计数器,比较conditonal跳转)。 为了避免这种情况,你是坚持使用while和手动递增循环计数器...

奇怪的是,F# 确实允许非int32循环边界,如果for表达被包裹在一个序列表达,例如

seq { for i = 0I to 10I do
        printfn "%A" i }

所以,我想的问题是:是否有仅允许特定的原因int32 for循环? 而为什么这种限制并不适用于for包裹在循环seq的表达?

Answer 1:

我不知道为什么F#不允许int64范围。 这听起来像一个非常有用的功能...(但是我能理解int是标准的类型在C#,也许F#试图遵循这种模式)。

至于解决方法,这是值得补充的是,你还可以写inline高阶函数:

let inline longFor low high f = 
  let rec loop n =
    if n < high then f n; loop (n + 1L)
  loop low

...然后你可以表达for循环过int64在一个相当简洁的方式范围:

longFor 1L 100L (fun n -> 
  <whatever> )

我做了几个实验和它似乎是F#编译器能够相当体面优化这个(lambda函数内联和尾递归loop功能变成一个while环)。 我不认为这是保证 ,所以你可能需要通过高性能的代码手来检查这一点,但它似乎好工作更简单的例子。

只有一个缺点-你将不能够使用本地可变变量( let mutable ),因为这些不能用lambda函数被捕获。 所以有可能是间接的额外费用ref细胞(但我不知道问题有多大,这是)。



Answer 2:

如果你想保持for循环,有一个非常简单的工作,周围用了...在同一个循环序列范围操作 :

for i in 0I .. 10I do
    printfn "%A" i

只要这两种类型的匹配范围运营商将接受任何规模的整数。 例如,以下不会编译:

for i in 0 .. 10I do
    printfn "%A" i


Answer 3:

另一种可能的解决方法:

[1L..100L] |> List.iter(乐趣I - > printfn “%i” 的ⅰ)



文章来源: Why are simple for loop expressions restricted to integer ranges?