2010-02-02 7 views
6

T4 ist die "offizielle" Codegenerierungs-Engine für C#/VB.NET. Aber F# doesn't support it (das ist von April, aber ich konnte keine neueren Erwähnungen finden). Also, was ist eine gute Möglichkeit, F # -Code zu generieren?Generierung von F # -Code

EDIT:

I 2-3 finger trees in F # implementieren möchten. Ich habe sie bereits in C# implementiert, also sollte das ein schöner Vergleich sein. Die „Ziffern“ und Knoten des Baumes können als Arrays dargestellt werden, so

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

jedoch die maximale Größe dieser Arrays ist sehr klein, so wäre es schön, haben

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 

um Grenzen zu vermeiden, etc.

Aber dann alle Funktionen auf Ziffer und Knoten von Hand zu schreiben wird schwieriger, und es ist besser, sie zu generieren. Und ein T4-ähnlicher Ansatz sieht perfekt dafür aus ...

+0

Ich werde nur werfen [diese] (https://github.com/kerams/Templatus) gibt. Es ist etwas, das ich kürzlich zusammengehackt habe. – nphx

Antwort

7

Da F # benutzerdefinierte Tools im Solution Explorer nicht unterstützt, können Sie Ihre T4-Dateien in ein C# - oder Visual Basic-Projekt einfügen und deren Ausgabe an Ihr F # -Projekt umleiten. Hier ist, wie Sie es mit T4 Toolbox tun können:

<#@ 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

Leider wird dadurch Module2.fs zum * bottom * von Library1.fsproj hinzugefügt und die Reihenfolge der Quelldateien ist in F # wichtig :-( –

+1

"Weil F # keine benutzerdefinierten Tools im Solution Explorer unterstützt", nicht sicher, was Sie damit meinen dass wir in unseren F # -Projekten immer die eigenen Werkzeuge verwenden: FsYacc, FsLex, Testgeneratoren und andere MSbuild - Erweiterungen, je nach Reihenfolge der Auswertung, fügen Sie die Dateien in der richtigen Reihenfolge in die * .fsproj - Dateien ein Aktualisieren Sie fsproj-Dateien nicht automatisch), oder fügen Sie sie unten hinzu und stellen Sie sicher, dass Abhängigkeiten durch vorhergehende, nicht automatisch generierte Dateien aufgelöst werden. – Abel

6

Es hängt davon ab, was Sie versuchen zu tun. Während es ein Ansatz ist, der nicht wirklich geeignet ist, Vorlagen in der Art und Weise zu erstellen, wie viele T4-Beispiele zeigen, würde ich im Allgemeinen empfehlen, eine "Kombinator-Bibliothek" [1] für Codegenerierung oder sprachorientierte Programmieraufgaben in F # zu entwerfen. Die Idee besteht darin, einige Kombinatoren zu entwerfen, die den Code darstellen, den Sie generieren möchten, indem Sie F-Quelltext aus Kombinatoren generieren und diesen dann über den Code-DOM kompilieren.

Wie oft es auch einfacher wäre, einfach einen Interpreter für Ihre Kombinatoren zu schreiben, anstatt Code zu generieren.

Gute Beispiele für combinators in F # sind:

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

+1

Nur zur Verdeutlichung - Sie schlagen vor, eine Kombinator-Bibliothek zu schreiben, die so etwas wie eine diskriminierte Gewerkschaftshierarchie ausgibt, die in den Quellcode übersetzt werden kann, oder? Im Gegensatz zur Verwendung von FParsec selbst, um Code zu generieren, meine ich. Ich möchte nur sicherstellen, dass es keine verborgene Funktion von FParsec gibt, von der ich nichts ahnte ... –

+0

Ja, ein guter Ort zum Starten wäre ein Unionstyp, der in F # -Code übersetzt werden könnte. FParsec war nur ein Beispiel für eine Kombinator-Bibliothek, es erzeugt keinen F # -Code, zumindest soweit ich weiß. – Robert

1

ich meistens mit Robert zustimmen (obwohl es sicherlich einige Situationen, in denen mit T4 von F # könnte sehr nützlich sein). Wie auch immer, vielleicht wäre es interessant zu wissen, warum möchten Sie F # -Code generieren? Dann könnten wir vielleicht eine typische funktionale Lösung für das Problem vorschlagen :-).

+0

Mein Anwendungsfall hinzugefügt. –

+0

Ich fürchte, ich habe keine gute Idee, wie ich das elegant lösen könnte - ich hatte vor einiger Zeit ein ähnliches Problem und habe keinen guten Weg gefunden. Selbst wenn T4 (oder ähnlich) funktioniert, würde es immer noch alle F # Bearbeitungszeit-Typ-Überprüfung brechen, was ziemlich ärgerlich wäre. In OCaml wird dies von Campl4 (http://en.wikipedia.org/wiki/Camlp4) gelöst, aber es gibt keine Entsprechung für F # (und ich fürchte, es gibt nur eine begrenzte Notwendigkeit dafür, besonders im Vergleich zu anderen) mögliche F # Verbesserungen). –

+1

In Bezug auf Arrays vs. Tupel - Ich denke, dass die Leistung von Arrays (mit Grenzen Überprüfung) möglicherweise nicht so schlecht ist (schließlich könnte die CLR in vielen Fällen Kontrollen vermeiden). Sie können jedoch auch eine funktionale Lösung mit F # -Listen versuchen (wenn Sie direkte Indizierung vermeiden können), weil sehr kleine Listen ziemlich schnell sein sollten (leider habe ich keine Nummern). –

3

Ich sah mich nach verschiedenen Optionen um und endete mit meinen relativ einfachen und statischen Codegenerierungsanforderungen mit einem * .fsx-Skript, das einen TextWriter mit fprintf verwendet, um den generierten F # -Code auszugeben.

Ich verwende tatsächlich FParsec für einige Parsing-Arbeit, aber da ich nicht von einer anderen Syntax in F # übersetzen, haben die beiden Teile wenig miteinander zu tun.

+0

Dies könnte ausreichen. –

+1

Sicher lieben diese Downvotes ohne einen Kommentar zu sagen, was mit meiner Antwort falsch ist. Ich lerne so viel von ihnen! –