2010-02-02 2 views
6

T4 является «официальным» механизмом генерации кода для C#/VB.NET. Но F# doesn't support it (это с апреля, но я не мог найти никаких новых упоминаний). Итак, что такое хороший способ генерировать код F #?Генерация кода F #

EDIT:

Я хочу осуществить 2-3 finger trees в F #. Я уже реализовал их на C#, поэтому это должно быть хорошее сравнение. «Цифры» и узлы дерева могут быть представлены в виде массивов, так

type 't FingerTree = Empty | Single of 't | Deep of 't array * (('t FingerTree) array) lazy * 't array 

Однако максимальный размер этих массивов очень мала, так что было бы неплохо иметь

type 't Digit = Digit1 of 't | Digit2 of 't*'t | Digit3 of 't*'t*'t | Digit4 of 't*'t*'t*'t 
type 't Node = Node2 of 't FingerTree * 't FingerTree | Node3 of 't FingerTree * 't FingerTree * 't FingerTree 
type 't FingerTree = Empty | Single of 't | Deep of 't Digit * ('t Node) lazy * 't Digit 

во избежание проверки границ и т. д.

Но тогда все функции на Digit и Node вручную становятся более сложными, и их лучше создавать. И подход, подобный T4, идеально подходит для него ...

+0

Я просто выбросить [это] (https://github.com/kerams/Templatus) там. Это то, что я недавно взломал. – nphx

ответ

7

Поскольку F # не поддерживает пользовательские инструменты в проводнике решений, вы можете поместить свои файлы T4 в проект C# или Visual Basic и перенаправить свой вывод на свой проект F #. Вот как вы можете сделать это с T4 Toolbox:

<#@ template language="C#" hostspecific="True" debug="True" #> 
<#@ output extension="txt" #> 
<#@ include file="T4Toolbox.tt" #> 
<# 
    FSharpTemplate template = new FSharpTemplate(); 
    template.Output.Project = @"..\Library1\Library1.fsproj"; 
    template.Output.File = "Module2.fs"; 
    template.Render(); 
#> 
<#+ 
class FSharpTemplate: Template 
{ 
    public override string TransformText() 
    { 
#> 
// Learn more about F# at http://fsharp.net 

module Module2 
<#+ 
     return this.GenerationEnvironment.ToString(); 
    } 
} 

#> 
+1

К сожалению, это добавит Module2.fs в * bottom * библиотеки1.fsproj и порядок исходных файлов важен в F # :-( –

+1

«Поскольку F # не поддерживает специальные инструменты в проводнике решений», не уверен, что вы подразумеваете под что при использовании пользовательских инструментов в наших проектах F # все время: FsYacc, FsLex, генераторы тестов и другие расширения MSbuild. В отношении порядка оценки либо включайте файлы в правильном порядке в файлах * .fsproj (и не обновляйте файлы fsproj автоматически) или добавьте их внизу и убедитесь, что зависимости разрешены предыдущими, неавтоматически генерируемыми файлами. – Abel

6

Это зависит от того, что вы пытаетесь сделать. Хотя это подход, который не подходит для создания шаблонов в способе, показанным многими примерами T4, в целом я бы рекомендовал разработать библиотеку «Комбинаторы» [1] для генерации кода или задач программирования на языке в F #. Идея состоит в том, чтобы сконструировать некоторые комбинаторы для представления кода, который вы пытаетесь сгенерировать, генерируя исходный текст F # из комбинаторов, а затем компилируя его с помощью кода DOM.

Однако часто проще было бы написать интерпретатор для ваших комбинаторов, а не генерировать код.

Хорошие примеры комбинаторов в F # являются:

[1] http://en.wikipedia.org/wiki/Combinator_library

+1

Просто для пояснения - вы предлагаете писать библиотеку combinator, которая выводит что-то вроде дискриминации иерархии профсоюзов, которая может быть переведена в исходный код, не так ли? В отличие от использования FParsec для генерации кода, я имею в виду. Я просто хочу убедиться, что нет никакой скрытой функции FParsec, о которой я не знал ... –

+0

Да, хорошим местом для начала будет тип объединения, который может быть переведен в код F #. FParsec был всего лишь примером библиотеки комбинаторов, он не генерирует код F #, по крайней мере, насколько мне известно. – Robert

1

я в основном согласен с Робертом (хотя есть конечно некоторые ситуации, когда использование T4 из F # может быть очень полезным). В любом случае, может быть, было бы интересно узнать , почему вы хотите сгенерировать код F #? Тогда мы могли бы предложить некоторое типичное функциональное решение проблемы :-).

+0

Добавил мой прецедент. –

+0

Боюсь, у меня нет хорошей идеи, как решить эту проблему - у меня была аналогичная проблема некоторое время назад, и я не нашел хорошего пути. Даже если T4 (или аналогичный) работал, он все равно нарушит проверку типа времени F #, что будет довольно неприятно. В OCaml это решается Campl4 (http://en.wikipedia.org/wiki/Camlp4), но для F # нет эквивалентной вещи (и я боюсь, что для этого существует только ограниченная потребность, особенно по сравнению с другими возможные улучшения F #). –

+1

Что касается массивов против кортежей - я думаю, что производительность массивов (с проверкой границ) может быть не такой плохой (после этого CLR во многих случаях может избежать проверок). Тем не менее, вы также можете попробовать функциональное решение, используя списки F # (если вы можете избежать прямой индексации), потому что очень маленькие списки должны быть довольно быстрыми (но у меня нет никаких цифр, к сожалению). –

3

Я огляделся по разным параметрам и в итоге получил свои относительно простые и статические потребности в генерации кода, используя скрипт * .fsx, который использует TextWriter с fprintf, чтобы записать сгенерированный код F #.

Я действительно использую FParsec для некоторой работы синтаксического анализа, но поскольку я не переводил с другого синтаксиса на F #, эти две части имеют мало общего с друг другом.

+0

Этого может быть достаточно. –

+1

Несомненно, любите эти нисходящие круги без комментариев, чтобы сказать, что случилось с моим ответом. Я многому от них научился! –

Смежные вопросы