|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||
|
Inscription : novembre 2011 Messages : 30 ![]() |
Bonjour, je dois charger un dictionnaire de 300.000 mots, seulement j'explose la pile... Stack overflow during evaluation (looping recursion?).
J'ai bien vu quelques sujets qui parlent de la récursivité terminale, etc... mais pas de réelle solution. Voilà ma fonction : Code :
Merci |
||
|
|
00
|
|
|
#3 |
|
Inscription : novembre 2011 Messages : 30 ![]() |
Oui, sauf que j'ai déjà eu bien du mal à faire cette fonction, j'ai pompé la moitié... J'ai fait 3 séances de caml donc, je suis pas contre un meilleur coup de pouce.
|
|
|
00
|
|
|
#4 | ||||
|
Membre Expert
![]() Yankel ScialomIngénieur en systèmes embarqués Inscription : juin 2004 Messages : 998 ![]() |
Pour faire court*, le principe de la récursivité terminale (qui est indépendante de la syntaxe OCaml) est de transmettre aux sous-appels le résultat partiel construit jusque là ; chaque itération (appel de la fonciton récursive) transforme ou complète le résultat partiel, jusqu'à parfaire la condition d'arrêt ; il n'y a plus qu'à retourner le résultat tout prêt.
Un exemple t'aidera à mieux comprendre. Tu trouveras l'exemple du calcul de la factorielle en rec term un peu partout sur le web ; en voici un autre : la somme de tous les éléments d'une liste (dans un cas réel, préférer l'usage de List.fold_left (+) 0) : Code :
Comme tu le vois, dans sum_list_elements (qui n'est pas récursive, inutile), on crée une fonction auxiliaire qui elle fait le travail ; mais elle demande un argument supplémentaire (on verra après pourquoi) qui est zéro ; plutôt que de donner à l'utilisateur cette fonction à l'usage particulier, on l'encapsule dans une fonction bien plus claire (qui est sum_list_elements et qui prend tout simplement en argument une liste d'entiers). La fonction aux prend donc deux arguments. Le second est une liste d'entiers à sommer. Le premier, appelé accumulateur (et ça prend tout son sens ici Voici ce que fait la fonction aux :
Exemple pour aux 0 [1;2;3] Code :
Avec de la rec term, l'appel père n'a pas besoin de traiter le résultat du fils, car le fils a en main toutes les informations nécessaires (la somme des éléments précédents et la liste des éléments suivant dans notre cas). OCaml peut donc « oublier » les appels parents et libérer la pile. J'espère que j'ai été clair, désolé pour le long message, je suis en forme aujourd'hui. Edit (*) HAHA !
__________________
gasp in touch -- Yankel Scialom |
||||
|
|
00
|
|
|
#5 | ||||||
|
Inscription : novembre 2011 Messages : 30 ![]() |
Salut prgasp77,
avant tout je te remercie pour ta réponse et le temps que tu as consacré à m'expliquer. Effectivement, avant même d'entendre parler de récursivité terminale, j'avais bien eu l'intuition de procéder ainsi, c'est à dire découper la tache en repassant la liste déjà créée à chaque nouvel appel de fonction jusqu'à avoir lu tout le fichier... Algorithmiquement parlant, ça ne me pose aucun problème, enfin je vois la chose ainsi : Lis mon fichier, après N lignes lues, rappelle la fonction et passe lui en argument la liste déjà crée à laquelle tu ajoutes (: Je vais essayer de modifier ma fonction en prenant ton exemple en modèle. C'est très frustrant car je comprends très simplement la manière dont tu expliques la chose mais quand je jette un oeil au code, ça coule pas du tout comme de l'eau de source à certains endroit... Et quand j'essaye du coup de faire pour lire un fichier, ça complexifie davantage et m'égare... J'essaye... edit : Après 40 minutes : Code :
# let charge = function (st) -> val charge : string -> 'a list list = <fun> # let rec lire file = val lire : in_channel -> string list list = <fun> ça me renvoie une liste de liste... Je n'vois pas quoi faire d'autre... J'ai tenté pleins de choses mais rien ne fonctionne... Edit : Après 50 minutes : J'aurai bien tenté : Code :
Edit : Après plus d'une heure : C'est impossible... -_- Quelqu'un me donne une solution en itératif, je n'ai pas appris l'itératif avec ocaml et j'aimerai m'en préserver car on nous l'a interdit en cours... Après 1h30 : Code :
|
||||||
|
|
00
|
|
|
#6 | ||
![]() ![]() ![]() Nicolas ValléeIngénieur d'études Inscription : décembre 2005 Messages : 9 963 ![]() |
Tu ne fais pas vraiment de la récursivité terminale, tu te contentes juste "d'en faire un peu"
Par ailleurs, il faudrait ne pas inverser l'ordre de la liste... Code :
|
||
|
|
00
|
Copyright © 2000-2013 - www.developpez.com