J'essaie de trouver la "meilleure" implémentation d'un multi-argument "composer" dans Scheme (je sais que c'est un builtin dans certaines implémentations, mais supposons pour l'instant je suis en utilisant celui qui n'a pas cela).Schéma: Implémenter n-argument composer en utilisant pli
Pour avoir cette fonction de composition 2 argument I:
(define compose
(lambda (f g)
(lambda x
(f (apply g x)))))
Ceci a l'avantage que si le droit le plus fonction a besoin d'arguments supplémentaires, ceux-ci peuvent encore être passés par la fonction combinée. Cela a la propriété agréable que composer la fonction d'identité sur quelque chose ne change pas la fonction.
Par exemple:
(define identity
(lambda (x) x))
(define list1
(compose identity list))
(define list2
(compose identity list1))
(list2 1 2 3)
> (1 2 3)
Maintenant, pour faire un "n-argument" composé que je pouvais le faire: la propriété
(define compose-n
(lambda args
(foldr compose identity args)))
((compose-n car cdr cdr) '(1 2 3))
> 3
Mais ce ne conserve plus que belle "identité":
((compose-n identity list) 1 2 3)
> procedure identity: expects 1 argument, given 3: 1 2 3
Le problème est que la fonction "initiale" est utilisée pour la commande foldr. Il a construit:
(compose identity (compose list identity))
Alors ... Je ne suis pas sûr de la meilleure façon de contourner cela. « Foldl » semble être la meilleure alternative naturelle, parce que je veux qu'il commence par « identité » sur la gauche pas le droit ...
Mais une mise en œuvre naïve:
(define compose-n
(lambda args
(foldl compose identity args)))
qui fonctionne (doivent inverser l'ordre des applications de fonction):
((compose-n cdr cdr car) '(1 2 3))
> 3
ne résout pas le problème parce que maintenant je finis par avoir à mettre la fonction d'identité sur la gauche!
((compose-n cdr cdr car) '(1 2 3))
> procedure identity: expects 1 argument, given 3: 1 2 3
Il est comme, je dois utiliser « foldr » mais ont besoin d'une autre valeur « initiale » que la fonction d'identité ... ou une meilleure fonction d'identité? De toute évidence, je suis confus ici!
Je voudrais l'implémenter sans avoir à écrire une "boucle" de queue-récursif explicite ... il semble qu'il devrait y avoir une manière élégante de faire ceci, je suis juste coincé.
[ La réponse de Dirk] (http://stackoverflow.com/questions/1693181/scheme-implementing-n-argument-compose-using-fold/1693202#1693202) (depuis supprimé) avait la bonne idée: il suffit d'utiliser 'values' au lieu de 'identité'. C'est en fait la méthode que mon implémentation de 'compose' exploite:' (compose) 'retourne simplement' values'. –
Merci! Mon seul problème maintenant est que l'interpréteur de schéma que j'utilise ne prend pas en charge les valeurs appel-à-valeurs ...Existe-t-il un moyen d'implémenter des «valeurs» et des «call-with-values» en plus du schéma existant? –
J'ai développé un moyen de trier les fausses 'values' et les' call-with-values': un nouveau post à venir. :-) –