为什么简单的循环表达式被限制在整数范围内? [英] Why are simple for loop expressions restricted to integer ranges?
问题描述
int
aka int32
aka System.Int32
)限制 start
和 stop
,例如 for i = start to stop do
// do sth。
我想知道为什么这种for循环的迭代界限必须是 INT32
。为什么不允许 uint32
? 的int64
? bigint
?
我知道序列迭代表达式( for ... in ...
)可以遍历任意序列;但是需要分配一个迭代器,并调用 MoveNext
和 Current
循环可以是(增量计数器,比较,条件跳转)。为了避免这种情况,你坚持使用而
和一个手动增加循环计数器...
奇怪的是,如果表达式的被包装在一个中,F#不允许< - c $ c> int32
序列表达式,例如:
seq {for i = 0I to 10I do
printfn%Ai} $ b所以,我想问题是:是否有一个特殊的原因,只允许 int32 $ b $ / pre
$
for循环?为什么这个限制不适用于包含在 seq
表达式中的循环?
<解决方案我不知道为什么F#不允许 int64
范围。这听起来像一个有用的功能...(但我可以理解, int
是C#中的标准类型,也许F#试图遵循这种模式)。 >
至于变通方法,值得添加的是,您还可以编写 inline
高阶函数:
let inline longFor low high f =
let rec loop n =
if n <高于f n;循环(n + 1L)
循环低
...然后您可以表达 for
在 int64
范围内以相当简洁的方式循环:
longFor 1L 100L(fun n - >
< whatever>)
我做了一些实验,似乎F#编译器能够相当体面地优化它(lambda函数内联,尾递归 loop
函数变成,而
循环)。我不认为这是有保证的,所以你可能需要在高性能的代码中手工检查这个,但是对于简单的例子来说,它似乎工作得很好。
只有一个缺点 - 你将不能使用局部可变变量( let mutable
),因为这些变量不能被lambda函数捕获。所以可能会有额外的成本,间接 ref
单元格(但我不知道这是多大的问题)。
According to the F# spec (see §6.5.7), simple for loops are bounded by integer (int
aka int32
aka System.Int32
) limits start
and stop
, e.g.
for i = start to stop do
// do sth.
I wonder why the iteration bounds for this type of for loop are required to be int32
. Why not allow uint32
? int64
? bigint
?
I'm aware that sequence iteration expressions (for ... in ...
) can iterate over arbitrary sequences; that however requires allocating an iterator and calling MoveNext
and Current
and what not and can thus be considerably less efficient than a plain loop could be (increment counter, compare, conditonal jump). To avoid that, you are stuck with using while
and a manually incrementing loop counters...
Strangely enough, F# does allow non-int32
loop bounds, if the for
expression is wrapped in a sequence expression, e.g.
seq { for i = 0I to 10I do
printfn "%A" i }
So, I guess the question is: Is there a particular reason for only allowing int32
for loops? And why does this restriction not apply to for
loops wrapped in seq
expressions?
I'm not sure why F# does not allow int64
ranges. It sounds like a useful feature... (but I can understand that int
is the standard type for this in C# and perhaps F# tries to follow this pattern).
As for the workarounds, it is worth adding that you can also write inline
higher-order function:
let inline longFor low high f =
let rec loop n =
if n < high then f n; loop (n + 1L)
loop low
...and then you can express for
loops over int64
ranges in a fairly succinct way:
longFor 1L 100L (fun n ->
<whatever> )
I did a couple of experiments and it seems that the F# compiler is able to optimize this fairly decently (the lambda function is inlined and the tail-recursive loop
function is turned into a while
loop). I do not think this is guaranteed so you may need to check this by hand in high-performance code, but it seems to work fine for simpler examples.
There is only one disadvantage - you won't be able to use local mutable variables (let mutable
) because these cannot be captured by a lambda function. So there may be additional cost with indirect ref
cells (but I'm not sure how big problem this is).
这篇关于为什么简单的循环表达式被限制在整数范围内?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!