Ist es möglich, Typen zu definieren, die voneinander abhängig sind und werden in getrennten Dateien definiert?

StackOverflow https://stackoverflow.com/questions/3983509

Frage

Ich versuche, eine Bibliothek mit erweiterten Analysefunktionen zu implementieren. Ich entschied, dass ich fsyacc wird, weil ich es von der Universität kannte. Leider traf ich Problem nach.

I definiert eine Klasse für den Kopf meiner Grammatik ( Kopf ) und legen ihre Umsetzung in einer einzigen Datei. Dann definierte I-Parser wie:

...
%start head
%type <Head> head
...

Fsyacc erzeugt seeparated Modul ( Parser ). Um erfolgreich zu sein hat es in folgenden Reihenfolge erstellt werden: Head.fs Parser.fs

Um diese Bibliothek ähnlich zu machen, was Sie in .NET ich finden kann, möchte eine statische Parse Methode Kopf hinzuzufügen. Ich müsste Einsatz von Methoden aus der Parser Modul.

machen leider

ich weiß, dass eine solche Typ Abhängigkeiten mit lösende ‚ und ‘ Betreiber, aber es ist nur für Typen in einer Datei definiert.

Gibt es eine andere Art und Weise Arten zu schaffen, die auch voneinander abhängig sind, wenn sie in separaten Dateien sind? Ich war auf der Suche nach Erklärung / Umsetzung Trennmechanismus, wie die in C / C ++, aber ich couldn ‚t find nichts.

War es hilfreich?

Lösung

Kurze Antwort: nein. Es gibt keine Möglichkeit für beide Seiten rekursive Einheiten über mehrere Dateien in F # 2.0 zu tun. (Dies ist etwas, das wir Adresse in der nächsten Version der Sprache zu planen.)

Sie können arbeiten, um diese in einer Vielzahl von Möglichkeiten, in der Regel einen Punkt Indirektionsebene und Mutation verwendet wird. Zum Beispiel könnte Ihr Kopf Typ eine statische ‚InitializeParser‘ Methode, die einen Funktionswert in eine veränderbare globale Variable stochert, und dann über diese wandelbar global ruft die statische Parse-Methode definierte in Kopf könnte, und nach dem Parser definiert eigentlich, es gehen und rufen sie können InitializeParser den Wert in stecken. (Wenn das nicht Sinn machen, kann ich es buchstabieren im Detail.)

Andere Tipps

Ich hatte gehofft, dass es möglich ist. Nachdem ich Brian Antwort lesen begann ich für eine richtige Abhilfe suchen. Ich wollte nicht, Bibliotheksbenutzer zwingen, keine Initialisierung Methoden aufrufen. Deshalb kam ich mit etwas diffrent auf.

Wenn Compiler können keine Abhängigkeiten zur Compile-Zeit löst ich es während der Laufzeit auf meinem eigenen tun. Hier ist Definition meiner DepencendciesResolver

module DependenciesResolver = 
    let GetMethod(_type, _method) =
        lazy (
            let a = System.Reflection.Assembly.GetExecutingAssembly()
            let t = a.GetType(_type)
            t.GetMethod(_method)
            )

Und Beispiel von Klassen in getrennten Dateien definiert:

A.fs

namespace MutualRecursion
type A() =
    static member _b = DependenciesResolver.GetMethod("MutualRecursion.B", "b")
    static member b() = A._b.Value.Invoke(null, [||])

B.fs

nameespace MutualRecursion
type B =
    static member b() = 
        printf "Called b()"

Compilation Reihenfolge ist: A.fs B.fs

Sie kann nicht arbeiten, um diese mit einer dritten Datei, die kompiliert, nachdem diese zwei und Leiter erstreckt sich mit der neuen Methode?

Ich würde so etwas wie die folgende (was ich vermute, grob ist, was Brian vorschlägt). Beachten Sie, dass die Benutzer hat keine schwierige Initialisierung zu tun -. Die Typen selbst wissen, wie man „den Bund fürs Leben“

Head.fs

type IParser =
  abstract Parse : string -> int // or whatever
  ...

type Head() =
  static let mutable parser = Unchecked.defaultof<IParser>
  static member internal SetParser p = parser <- p
  member x.DoSomethingCool() =
    let i = parser.Parse("something to parse")
    ...

Parser.fs

type Parser private () =
  static do
    Head.SetParser (Parser())
  interface IParser with
    member x.Parse s = 0
    ...
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top