代码之家  ›  专栏  ›  技术社区  ›  Snark

F#范围是在编译时还是运行时计算的

  •  1
  • Snark  · 技术社区  · 14 年前

    在这两种情况下,这是什么表现?i、 有没有可能建立一个定制的功能,使这些操作更快?

    2 回复  |  直到 14 年前
        1
  •  3
  •   Tomas Petricek    14 年前

    我认为 千伏安 回答了大多数问题。然而,我认为一个更精确的答案是评估范围 在运行时懒惰地

    例如,当您使用 1 .. 10 在代码的某个地方,它被简单地转换为某个方法调用。调用取决于所使用的上下文和数字类型。

    • [ 1 .. 10 ] 或其他序列表达式和 for 循环,编译器将生成 RangeInt32(1, 1, 10) (附加参数是步骤)。

    • obj.[ 1 .. ] obj 是某个支持切片的对象(例如矩阵类型),则将其转换为 obj.GetSlice(Some(1), None)

    现在很容易回答您的问题—这是一个将在运行时进行评估的方法调用。但是,需要注意的是,可能不需要对整个范围进行评估!例如:

    let nums = seq { 1 .. 10 } |> Seq.take 1
    

    序列表达式将被转换为对的调用 RangeInt32 . 这将只返回类型为的值 seq<int> take 1 只接受第一个元素,因此只需要并计算范围中的第一个数字。

    我不认为您自己的范围实现与标准范围实现有任何不同,但是您可以作为对象的成员提供您的实现。然后你就可以写了 myObj.[1 .. 10] (结果可以是您想要的任何类型)。为此,需要一个实例方法 GetSlice ,更详细 discussed here .

        2
  •  3
  •   kvb    14 年前

    运行时间。F#很少会在编译过程中运行您的代码—我能想到的唯一情况是 NumericLiteralX 模块。此外,在这样的代码中:

    let f n = [1 .. n]
    

    int ),但从语义上讲,它应该始终与在运行时执行的操作相同。

    关于你的第二个问题,比什么更快?