2012-05-19 5 views
6

"Introduction to Caml" ditPourquoi préférer tuple des arguments dans OCaml?

Note, en Caml, il est préférable d'utiliser des définitions de fonctions cari pour les fonctions multiples arguments, non tuples.

lors de la comparaison des conventions d'appel 'a -> 'b -> 'c à 'a * 'b -> 'c. Lorsque je travaillais avec SML/NJ, je m'étais habitué à utiliser des types de tuple pour l'entrée et la sortie: ('a * 'b) -> ('c * 'd) donc l'utilisation de tuples pour exprimer plusieurs entrées semble symétrique avec la façon dont j'exprime plusieurs sorties.

Pourquoi l'exécution de la fonction OCaml est-elle recommandée pour les arguments de type tuple? S'agit-il simplement de la plus grande souplesse qui permet d'autoriser l'évaluation partielle/partielle, ou y a-t-il d'autres avantages qui découlent des détails d'implémentation du compilateur OCaml?

+2

Le choix de l'exécution de la plupart des fonctions dans Caml-light et les versions suivantes est expliqué dans le rapport "L'expérience ZINC: une implémentation économique du langage ML". Une chose dont je me souviens est qu'avec le schéma d'évaluation approprié (décrit dans le rapport), une fonction au curry ne nécessite aucune allocation pour être appelée. http://caml.inria.fr/pub/papers/xleroy-zinc.ps.gz –

+0

@PascalCuoq, alors qu'un tuple doit être alloué, déballé, puis GCed? –

+0

Oui, si la fonction est également appelée avec des tuples préexistants ('ft'), il n'y a aucun moyen de contourner le fait qu'un éphémère éphémère' (x, y) 'doit être alloué pour s'appliquer' f' quand on n'a que «x» et «y». –

Répondre

2

Oui, c'est principalement la commodité de la notation et la flexibilité de faire une application partielle. Les fonctions du cari sont idiomatiques dans OCaml, et le compilateur est susceptible de les optimiser quelque peu mieux que les fonctions triées (alors que les compilateurs SML optimisent généralement pour les tuples). Les avantages du couplage sont la symétrie argument/résultat que vous mentionnez (ce qui est particulièrement utile lors de la composition des fonctions) et peut-être la familiarité notationnelle (au moins pour les personnes venant du monde non-fonctionnel).

1

Quelques commentaires sur l'optimisation dans OCaml.

Dans OCaml, j'ai remarqué que les tuples sont toujours alloués lors du passage en argument. Même si allouer dans le tas primaire est rapide en ocaml, il est bien sûr plus long que de ne rien faire. Ainsi, chaque fois que vous passez un tuple en argument, il y a un peu de temps pour l'allocation et le remplissage du tuple.

Je m'attendais à ce que le compilateur ocaml optimise les cas où il n'est pas nécessaire de construire le tuple. Par exemple, lorsque vous insérez la fonction appelée, vous ne pouvez utiliser que les composants du tuple et non le tuple lui-même. Ainsi le tuple pourrait juste être ignoré. Malheureusement dans ce cas OCaml ne supprime pas le tuple inutile et continue d'effectuer l'allocation. Pour cette raison, il peut ne pas être une bonne idée d'utiliser des tuples dans les sections critiques du code.

+0

Je pense que ce n'est plus vrai. ["OCaml est plus intelligent que je ne le pensais"] (https://blogs.janestreet.com/ocaml-is-smarter-than-i-thought/) dit "J'avais empêché l'inline, mais il n'y avait toujours pas d'allocation! Eh bien, il s'avère qu'OCaml peut optimiser une fonction de prise de ligne pour faire passer les éléments du tuple via des registres, ce qui est exactement ce qui s'est passé, et le compilateur s'est rendu compte qu'aucune allocation n'était nécessaire. –

5

Je pense que c'est en grande partie conventionnel - les fonctions de bibliothèque standard dans OCaml sont cariées, alors qu'en ML standard, elles ne le sont généralement pas à l'exception de certaines fonctions d'ordre supérieur. Cependant, il existe une différence cuite dans le langage: les opérateurs (par exemple (*)) sont caramélisés dans OCaml (par exemple int -> int -> int); alors qu'ils ne sont pas séchés dans la norme ML (par exemple op* peut être (int * int) -> int). A cause de cela, les fonctions d'ordre supérieur intégrées (par exemple, fold) prennent également une fonction qui est caramélisée dans OCaml et non diluée dans Standard ML; cela signifie que pour que votre fonction fonctionne avec cela, vous devez suivre la convention respective, et cela résulte de là.

+1

Bon point. Il existe une autre instance dans laquelle le choix est cuit: les constructeurs de type de données. En SML ils sont tuplés, chez Haskell ils sont caris. Curieusement, dans OCaml, ils sont triés, ce qui est un peu un décalage avec le reste de la langue. –

+1

La signification profonde derrière les constructeurs de type de données en cours de triplement est qu'un tuple est un constructeur de données de cas particulier anonyme. –

Questions connexes