2016-06-17 4 views
1

Ich möchte eine Liste der erforderlichen Module eines bestimmten Moduls (sagen wir das aktuelle Modul).Ermitteln der Liste der erforderlichen Module durch ein Modul in Racket

Ich habe das Gefühl, dass es noch einige andere Möglichkeiten gibt (wie das Parsen des Moduls?), Aber ich habe mit der Idee des Shadowings (require) angefangen und die benötigten Elemente zu einer Hash-Tabelle mit dem Modul hinzugefügt -Name. Das Problem ist, ich kann nicht herausfinden, wie man eine Syntaxdefinition dafür schreibt.

Obwohl nicht funktioniert, eine Funktionsdefinition Äquivalent würde wie unten sein:

(define require-list (make-hash)) 
(define require 
    (lambda vals 
    ; add vals to hash-table with key (current-namespace) 
    (let ([cn (current-namespace)]) 
     (hash-set! require-list cn 
       (append vals (hash-ref require-list cn)))) 
    (require vals))) 

.. es scheint, die letzte Zeile Aufruf geändert werden sollte, das Original (erforderlich) als auch anrufen?

Eine korrekte Version oder ein Zeiger auf, wie man es macht, oder irgendeine andere Weise, das ursprüngliche Ziel zu erreichen, das sehr geschätzt wird.

Antwort

2

Wenn Sie nur eine Liste der Importe für ein bestimmtes Modul erhalten möchten, gibt es ein praktisches eingebautes module->imports, das tun wird, was Sie wollen. Es wird eine Zuordnung zwischen Phasenebenen und Modulimporten zurückgegeben - Phasenstufen höher als 0 zeigen an, dass zur Kompilierungszeit für die Makroerweiterung verwendete Importe verwendet werden.

> (require racket/async-channel) 
> (module->imports 'racket/async-channel) 
'((0 
    #<module-path-index:(racket/base)> 
    #<module-path-index:(racket/contract/base)> 
    #<module-path-index:(racket/contract/combinator)> 
    #<module-path-index:(racket/generic)>)) 

Beachten Sie, dass das betreffende Modul in den aktuellen Namensraum, um für module->imports enthalten sein müssen, zu arbeiten, die require oder dynamic-require wird beides tun.

Dadurch werden die vom Compiler bekannten Informationen geprüft, so dass alle statischen Importe für ein bestimmtes Modul gefunden werden. Die von John Clements erwähnten Einschränkungen bezüglich dynamischer Anforderungen gelten jedoch weiterhin: Diese können zur Laufzeit dynamisch ausgeführt werden und werden daher von module->imports nicht erkannt.

+0

Das sieht ziemlich beeindruckend aus, fast, wonach ich suche! Für meinen aktuellen Zweck ist das Mapping der Phase 0 ausreichend. Ich wundere mich auch, wenn ich das in einer Funktion in einem anderen Modul anrufe, gibt es eine Möglichkeit, den Modulnamen des Anrufers zu bekommen? Ich bin derzeit im Namespacebereich der Referenz verloren. – MattAPiroglu

2

Kurze kurze Version:

Haben Sie versucht, den Modulbrowser einzuschalten?

Kurzversion:

  • Sie gehen ein Makro dafür benötigen, und
  • Es ist nicht eine komplette Lösung

Die bestehende require ist keine Funktion sein würde; Es ist eine Sprachform, implementiert als Makro. Dies liegt daran, dass der Compiler die gleichen Informationen sammeln muss wie Sie und daher müssen die erforderlichen Module zur Kompilierungszeit bekannt sein.

Der richtige Weg, dies zu tun - wie Sie vorschlagen - ist definitiv, das vorhandene Parsing zu nutzen. Wenn Sie das Modul erweitern und dann den resultierenden Baum durchlaufen, sollten Sie in der Lage sein, alles zu finden, was Sie brauchen. Der Baum wird extrem groß sein, aber eine relativ kleine Anzahl von Primitiven enthalten (viele Beispiele davon), daher sollte das Schreiben dieser Traversierung nicht zu schwierig sein. Es wird jedoch viel Fiedeln in die Einrichtung von Namespace-Ankern etc. involviert sein, um die Expansion überhaupt erst möglich zu machen.

In Bezug auf Ihre ursprüngliche Idee: Sie können definitiv ein Makro erstellen, das Schatten erfordert. Sie werden es in einer anderen Datei definieren und auf dem Weg nach außen umbenennen wollen, damit sich Ihr Makro auf die ursprüngliche Anforderung beziehen kann. Außerdem hat das Formular require eine Reihe interessanter Unterformulare, und es wird schwierig sein, ein Makro zu entwickeln, das versucht, alle diese Unterformulare zu verarbeiten. Wenn Sie jedoch ein Makro schreiben, denken Sie bereits über eine 80% Lösung nach, also wird Sie das vielleicht nicht stören.

Schließlich gibt es Formulare, die dynamische Modulauswertung durchführen, und so können Sie nicht sicher alle Module wissen, die erforderlich sein können, obwohl Sie möglicherweise diese Formulare annotieren können (oder das dynamische Modul-Laden möglicherweise überschatten) Funktion), um diese zu sehen, wie sie geschehen.

Es ist auch erwähnenswert, dass Sie genauere Antworten auf der Racket Mailingliste erhalten können.

+0

Danke für die Hinweise, John. Ich werde ein Shadowing-Makro versuchen, wenn ich ein wenig mehr mit Makros vertraut bin, zur Hash-Tabelle hinzufügen und dann das Original require für den normalen Vorgang aufrufen. Ah, und ja, ich sollte auch versuchen, die Mailingliste zu benutzen. – MattAPiroglu