所以我的意思是循环展开就像
Write "Hello" |> Repeat 5
- >>>
Write "Hello"
Write "Hello"
Write "Hello"
Write "Hello"
Write "Hello"
据我所知,这是一些优化,如果可能的话,我只是感兴趣
顺便说一句 - 简单地说为什么我必须在[0..4]中使用...如果我真的不是这个[0..4]并且我真的不需要这个我...
答案 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