Il semble que votre méthode de récursion sur la queue d'un noeud de liste est le problème. Au lieu de treeFun h
ajouté à treefun (NODE(t))
, essayez d'utiliser ceci pour le nœud case:
treeFun (NODE(items)) = ["("] @ List.concat (map treeFun items) @ [")"]
C'est-à-dire, la carte treeFun
sur tout le contenu du nœud, et entourer les résultats avec "("
et ")"
. Cette définition pourrait être un peu trop laconique pour vous de comprendre ce qui se passe, alors voici une forme plus bavard que vous trouverez peut-être plus claire:
| treeFun (NODE(items)) =
let val subtree_strings : string list list = map treeFun items
val concatenated_subtrees : string list = List.concat subtree_strings
in ["("] @ concatenated_subtrees @ [")"]
end
subtree_strings
est le résultat de prendre toutes les sous-arbres dans le noeud donné, et transformer chacun d'entre eux en une liste de chaînes en appelant récursivement treeFun
sur chaque sous-arbre. Puisque treeFun
renvoie une liste de chaînes à chaque fois qu'elle est appelée, et que nous l'appelons sur une liste entière de sous-arborescences, le résultat est une liste correspondante de listes de sous-arborescences. Ainsi, par exemple, si nous appelions map treeFun [LEAF 1, LEAF 2, LEAF 3]
, nous obtiendrions [["1"], ["2"], ["3"]]
.
Ce n'est pas la réponse que nous voulons, car c'est une liste de listes de chaînes plutôt qu'une liste de chaînes de caractères. Nous pouvons corriger cela en utilisant List.concat
, qui prend une liste de listes, et forme une seule liste de tous les éléments sous-jacents. Par exemple, List.concat [["1"], ["2"], ["3"]]
renvoie ["1", "2", "3"]
. Maintenant tout ce que nous avons à faire est de mettre les parenthèses autour du résultat, et nous avons fini.
Notez que cette stratégie fonctionne aussi bien pour les noeuds complètement vides que pour les noeuds avec un ou plusieurs sous-arbres, ce qui élimine le besoin du deuxième cas de treeFun
dans votre définition d'origine. Généralement, dans ML, c'est une odeur de code si une fonction d'un argument n'a pas exactement un cas pour chaque constructeur du type de l'argument.
Merci pour le conseil. Je me rends compte que j'ai besoin de cartographier les choses mais le problème est que je ne sais pas vraiment comment le mapper correctement dans SML. J'ai essayé pendant environ 4 heures maintenant, mais il n'y a pas de vrais tutoriels pour ma situation. J'ai essayé "| treeFun (NODE (h :: t)) = [" ("] @ (carte (fn y => y = treeFun (h)) [(treeFun (NODE (t)))]) @ ["]"] "Des choses comme ça mais des erreurs et j'ai essayé beaucoup d'autres méthodes mais je suis coincé. Pouvez-vous peut-être berner ce que je dois faire? Je vais continuer à travailler dessus mais tout autre conseil pourrait m'aider beaucoup. – user494948
J'ai mis à jour ma réponse pour être plus explicite. – jacobm
Merci pour la longue explication, je n'étais pas au courant que vous pouviez utiliser la fonction de carte comme ça. Cela m'aide beaucoup, surtout pour une autre fonction que je crée. – user494948