是否可以在F#中进行循环展开(完全在.net中)?

时间:2011-04-22 11:24:32

标签: .net f#

所以我的意思是循环展开就像

Write "Hello" |> Repeat 5

- >>>

Write "Hello"
Write "Hello"
Write "Hello"
Write "Hello"
Write "Hello"

据我所知,这是一些优化,如果可能的话,我只是感兴趣

顺便说一句 - 简单地说为什么我必须在[0..4]中使用...如果我真的不是这个[0..4]并且我真的不需要这个我...

3 个答案:

答案 0 :(得分:6)

F#语言不直接支持这种形式的元编程。您要求的通常称为多阶段编程,并且有支持它的基于ML的语言(例如搜索MetaML)。在这些语言中,您可以使用已编译的代码进行操作,并(例如)展开循环。

这种有限形式可以使用引文在F#中完成。但它不是很实用,因为F#引用编译器会生成较慢的代码(因此它肯定不能用作优化)。

然而,仅仅是为了好奇,这里是如何使用F#PowerPack中的引用和引用编译器来实现这一点:

#r @"FSharp.PowerPack.Linq.dll"
open Microsoft.FSharp.Linq.QuotationEvaluation

// Generate quotation that contains 5 prints followed by expression that returns unit
let unrolled = [ 1 .. 5 ] |> List.fold (fun expr _ -> 
    <@ printfn "Hello"; %expr @>) <@ () @>

// Compile the function once & run it two times
let f = unrolled.Compile()
f()
f()

...正如我所提到的,这对于优化来说没有用,因为Compile方法产生的代码很慢,但在其他一些场景中它很有用。

答案 1 :(得分:5)

您可以编写for _ in 0..4来表示您不需要循环变量的值。

在F#语言级别上执行类似循环展开的操作需要支持宏。在像Lisp或Clojure这样的语言中,你可以做到这一点。但通常最好让编译器或运行时担心这一点。

在IL级别上,您可以使用System.Reflection.Emit命名空间的类(或使用类似Cecil的库)来实现循环展开等操作。

答案 2 :(得分:3)

你不能没有'for',但你可以在你自己的函数中抽象它

let Write msg = 
    fun () -> printfn msg

let Repeat n f = 
    for _ in 1..n do
        f() 

Write "Hello" |> Repeat  5