Un peu d'arrière-plan en premier. J'apprends actuellement des trucs sur les combinateurs d'analyseurs monadiques. Alors que j'ai essayé de transférer la fonction « chainl1 » de this paper (. P 16-17), je suis venu avec cette solution:Fonctions récursives dans les expressions de calcul
let chainl1 p op = parser {
let! x = p
let rec chainl1' (acc : 'a) : Parser<'a> =
let p' = parser {
let! f = op
let! y = p
return! chainl1' (f acc y)
}
p' <|> succeed acc
return! chainl1' x
}
J'ai testé la fonction avec une entrée large et a obtenu un StackOverflowException. Maintenant, je me demande, est-il possible de réécrire une fonction récursive, qui utilise une expression de calcul, d'une manière qui utilise la récursivité de la queue?
Lorsque je développe l'expression de calcul, je ne vois pas comment cela serait généralement possible.
let chainl1 p op =
let b = parser
b.Bind(p, (fun x ->
let rec chainl1' (acc : 'a) : Parser<'a> =
let p' =
let b = parser
b.Bind(op, (fun f ->
b.Bind(p, (fun y ->
b.ReturnFrom(chainl1' (f acc y))))))
p' <|> succeed acc
b.ReturnFrom(chainl1' x)))
Cela se débarrasse de la récursivité à travers le code utilisateur, mais dans mon implémentation ici http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!1772.entry StackOverflows encore à travers l'implémentation de l'analyseur lui-même. Je vais maintenant être motivé pour enquêter sur les 'analyseurs avec suites' ... – Brian
Est-ce que FParsec http://www.quanttec.com/fparsec/ gère cela? – Brian
Brian, j'ai aussi utilisé votre série de blog comme source d'apprentissage. Cela a beaucoup aidé. Pendant ce temps, j'ai comparé la réponse de Mau («seq») avec mon analyseur. Et je suppose que la méthode Delay dans la monade est l'importation. Mais je ne sais vraiment pas. FParsec utilise 'while' ... mais je veux utiliser une solution fonctionnelle: D – PetPaulsen