Можно ли сделать разматывание цикла в F # (в .net вообще)? - PullRequest
3 голосов
/ 22 апреля 2011

так что я подразумеваю под разверткой цикла, как

Write "Hello" |> Repeat 5

- * >>> * 1004

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

Насколько я знаю, это некоторая оптимизация, и мне просто интересно, если это возможно на .NET

Кстати - просто, почему я должен использовать для i в [0..4] do ... если я действительно не это [0..4], и мне действительно не нужно это i .. .

Ответы [ 3 ]

6 голосов
/ 22 апреля 2011

Язык 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 создает медленный код, но он полезен в некоторых других сценариях.

5 голосов
/ 22 апреля 2011

Вы можете написать for _ in 0..4, чтобы указать, что вам не нужно значение переменной цикла.

Выполнение чего-либо вроде развертывания цикла на уровне языка F # потребует поддержки макросов.На таких языках, как Lisp или Clojure, вы можете сделать это.Но обычно лучше позволить компилятору или среде выполнения беспокоиться об этом.

На уровне IL вы можете реализовать такие вещи, как развертывание цикла, используя классы пространства имен System.Reflection.Emit (или используя библиотеку, такую ​​какчто).

3 голосов
/ 22 апреля 2011

Вы не можете обойтись без 'for', но вы можете абстрагировать его в своей собственной функции

let Write msg = 
    fun () -> printfn msg

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

Write "Hello" |> Repeat  5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...