2008-08-30 6 views
11

J'écris un interpréteur pour un langage expérimental. Trois des principales constructions du langage sont des définitions, des déclarations et des expressions. Les définitions peuvent contenir des instructions et des expressions, les instructions peuvent contenir des définitions et des expressions, et un type d'expression peut contenir des instructions. Je les représente tous en utilisant des types d'union, donc je peux facilement utiliser la correspondance de motifs sur eux. Idéalement, je voudrais mettre le code pour ceux-ci dans des fichiers différents, mais OMake se plaint de problèmes de dépendance circulaire. Pour autant que je sache, les définitions de type circulaire entre les modules ne sont pas autorisées.Gestion des dépendances circulaires dans OCaml

La seule façon que je connaisse pour résoudre ce problème est de définir les trois types à la fois:

type defn = ... 
and stmt = ... 
and expr = ... 

Il semble que cela nécessite tout le code pour les types d'être dans le même fichier. Y at-il un moyen de contourner cela? Comment gérez-vous les définitions circulaires dans votre code?

Répondre

15

Les définitions récursives doivent apparaître dans le même fichier. Si vous souhaitez séparer les définitions, les instructions et les expressions en modules distincts, vous pouvez le faire en utilisant recursive modules, mais ils devront toujours apparaître dans le même fichier. DAG-ifying interdépendances entre fichiers est l'un des ennuis de OCaml.

12

Ceci est facilement résolu en paramétrant vos types sur les types auxquelles ils se réfèrent:

type ('stmt, 'expr) defn = ... 
type ('defn, 'expr) stmt = ... 
type ('defn, 'stmt) expr = ... 

Cette technique est appelée « dénoue le nœud récursif » (en référence au noeud de Gordian) et a été décrit dans un article OCaml Journal .

À votre santé, Jon Harrop.

3

Une autre solution souvent utilisée est de faire abstraction des types dans les interfaces. Puisque les types sont abstraits dans les interfaces, ces interfaces ne dépendent pas récursivement. Dans les implémentations, vous pouvez spécifier les types, et puisque les implémentations ne dépendent que des interfaces, elles ne sont pas non plus récursives.

Le seul problème est que, avec cette solution, vous ne pouvez plus faire de mise en correspondance de modèles sur ces types en dehors de leur implémentation.

Personnellement, mais c'est probablement une question de goût, j'aime que tous les types de mon programme soient définis en un seul module (je pense que cela aide à la lisibilité du programme). Donc, cette restriction d'OCaml n'est pas vraiment un problème pour moi.

Questions connexes