IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

Fonction "à nombre variable d'arguments"


Sujet :

Caml

  1. #1
    Membre régulier
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    102
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2010
    Messages : 102
    Points : 110
    Points
    110
    Par défaut Fonction "à nombre variable d'arguments"
    [Le titre n'est pas exact, mais je ne savais pas trop quoi mettre d'autre et je me suis dit que c'était un truc susceptible d'être recherché]

    Salut,

    J'aimerais définir une fonction permettant de créer des fonctions prenant un nombre d'argument différent. Par exemple, si cette fonction s'appelait f et n'avait pour seule vocation que d'ignorer un nombre variable d'arguments, on aurait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    # f 0 ;;
    - : unit = ()
     
    # f 1 x ;;
    - : unit = ()
    etc... (On peut supposer que tous les arguments à ignorer sont de même type)

    Ma motivation initiale était de remplacer des trucs comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Format.fprintf out_fmt ...
    if verbose then Format.fprintf out_fmt ...
    if very_verbose then Format.fprintf out_fmt ...
    par quelque chose comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    print ...
    print_verbose ...
    print_very_verbose ...
    Mais comme il y a plein d'autres moyens de faire ça, ce n'est pas vraiment le problème. J'aimerais simplement voir comment ce genre de chose peut être fait.

    En gros, c'est ce que fait printf, qui prend un format lui indiquant le nombre de strings qui vont suivre. Du coup, j'ai jeté un coup d'oeil à l'implémentation de printf (http://caml.inria.fr/svn/ocaml/trunk/stdlib/printf.ml), seulement elle est rendue compliquée par le fait qu'elle fait quelque chose d'un peu plus sophistiqué que ma fonction... Et surtout j'ai vu qu'elle utilisait pas mal Obj.magic, qui est "interdit à moins de savoir ce qu'on fait" [comme ce n'est pas mon cas...].

    Comment pourrait-on faire cela ?

  2. #2
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut Labels et arguments optionnels
    La notion de 'nombre d'arguments' n'a pas beaucoup de sens en Caml.
    Exemple avec id, une fonction censée ne prendre qu'un seul argument :
    Hé bien on peut lui appliquer 4 arguments simplement en juxtaposant 4 expressions à sa droite :
    edit:
    Voilà, j'ai bricolé une fonction print qui 'prend un nombre quelconque d'arguments', formatés, sans utiliser Obj.magic:
    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let print u =
       u
    let int n u =
       print_int n; print_char ' '; u
    let string s u =
       print_string s; print_char ' '; u
    let char c u =
       print_char c; print_char ' '; u
    
    # print (int 4) (char 'f') (string "persons") ();;
    4 f persons - : unit = ()
    Je te recommande chaudement la lecture des chapitres 4.1 Labels et 4.1.1 Optional arguments.
    LablGtk utilise abondamment les arguments optionnels pour créer ses widgets avec beaucoup de flexibilité.
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  3. #3
    Membre régulier
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    102
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2010
    Messages : 102
    Points : 110
    Points
    110
    Par défaut
    Salut,

    Merci beaucoup pour ta réponse ! Néanmoins, elle ne me convient pas tout à fait car elle contourne le problème en appelant un dernier argument de type unit. Par exemple, si on revient à ma motivation initiale (même si je n'en ai pas grand chose à faire en réalité), ce que j'aurai aimé pouvoir faire c'est écrire directement quelque chose du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    let print = if verbose then Format.fprintf fmt else la_fameuse_fonction
    EDIT : d'ailleurs je crois que je j'avais voulu que ça compile il aurait fallu que je fasse
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    let print x = if verbose then Format.fprintf fmt x else la_fameuse_fonction x
    Comme ça j'aurai directement pu appeler
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print "blabla : %g" x;
    print "blablabli : %g - %g" x y;
    Mais en réalité, j'aimerais simplement savoir s'il est possible de définir une fonction telle que, par exemple :
    f : int -> 'a
    f 0 : unit
    f 1 : 'a -> unit
    f 2 : 'a -> 'a -> unit

    "Pour le principe".

    Je n'y arrive pas: Avec Obj.magic, ça marche mais :
    1. j'ai vu qu'il ne fallait pas le faire
    2. ça segfault quand trop d'arguments sont donnés
    J'ai essayé des trucs avec des types récursifs mais ça n'a rien donné.

    Enfin, j'avoue ne pas me servir énormément des Labels dans mes programmes mais j'en ai déjà utilisé dans plusieurs bibliothèques, et du coup je ne vois pas directement en quoi ça pourrait être utile pour ce problème...

  4. #4
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut print_newline ne me convient pas tout à fait
    J'ai le même "problème" avec print_newline, si je veux que cette fonction crée une nouvelle ligne je dois lui appliquer un argument de type unit.

    "Pour le principe" j'aimerais savoir comment appeler une fonction sans lui appliquer d'argument.

    J'ai un autre problème : quand j'utilise Obj.magic ça segfault.

    J'ai lu le chapitre sur les Labels et je n'ai rien trouvé qui réponde à mes attentes.
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  5. #5
    Membre régulier
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    102
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2010
    Messages : 102
    Points : 110
    Points
    110
    Par défaut
    Zut, pas d'autres réponses ?

    Bon en fait je n'avais pas fait attention mais ce n'est pas vraiment la printf qui fait le boulot, mais le type format... Du coup j'ai bien peur que ça ne soit tout simplement pas possible : si ça l'était, le type de notre fonction ne pourrait pas forcément être connu lors de la compilation (car il dépendrait de la valeur de l'argument, et pas de son type)

    Pour printf le problème ne se pose pas car la chaîne de caractère qui est interprétée en format doit être "hardcoded", et du coup le compilateur peut sans doute faire des trucs "impossibles" dessus en sortant d'OCaml...

    EDIT : à première vue, la fonction format_of_string semble contredire ce que je viens de dire car elle est capable de transformer une string en format... Seulement quand on regarde son type, ce n'est as string -> 'blabla format mais 'blabla format -> 'blabla format ! Donc il semble bien qu'il se passe des trucs bizarres avant l'appel à cette fonction (le compilateur - "sait" que la chaîne de caractère n'en est pas une et il l'interprète comme un objet bizarre...)

    Si quelqu'un en savait plus sur le sujet, toute remarque serait bienvenue !

  6. #6
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut
    Citation Envoyé par drunkskater
    le type format... Du coup j'ai bien peur que ça ne soit tout simplement pas possible : si ça l'était, le type de notre fonction ne pourrait pas forcément être connu lors de la compilation (car il dépendrait de la valeur de l'argument, et pas de son type)
    Quand quelqu'un montre qu'il a réfléchi moi je

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    f 1 : 'a -> unit
    f 2 : 'a -> 'a -> unit
    f 3 : 'a -> 'a -> 'a -> unit
    Techniquement il est possible d'unifier tous ces types.
    Voilà ce que ça donne, tout y est "bien typé" selon les spécifications demandées :
    Code Caml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let rec f x = f x;;
    (f 1 : 'a -> unit);;
    (f 2 : 'a -> 'a -> unit);;
    (f 3 : 'a -> 'a -> 'a -> unit);;
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  7. #7
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Citation Envoyé par drunkskater Voir le message
    EDIT : à première vue, la fonction format_of_string semble contredire ce que je viens de dire car elle est capable de transformer une string en format... Seulement quand on regarde son type, ce n'est as string -> 'blabla format mais 'blabla format -> 'blabla format ! Donc il semble bien qu'il se passe des trucs bizarres avant l'appel à cette fonction (le compilateur - "sait" que la chaîne de caractère n'en est pas une et il l'interprète comme un objet bizarre...)

    Si quelqu'un en savait plus sur le sujet, toute remarque serait bienvenue !
    format_of_string ne fonctionne que si la string donnée est connue lors de la compilation. Je ne sais plus dans quel cas j'en avait eu besoin, ça peut être utile mais ce n'est pas magique.
    -- Yankel Scialom

  8. #8
    Membre régulier
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    102
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2010
    Messages : 102
    Points : 110
    Points
    110
    Par défaut
    Salut,

    J'ai essayé d'en savoir plus sur comment le compilateur faisait pour créer les format, mais finalement j'ai décidé que ce n'était pas si intéressant que ça alors je laisse tomber.

    En tous cas merci SpiceGuid et prgasp77 pour votre aide. Même si ma question n'était pas très intéressante ça m'a forcé à réfléchir à plusieurs trucs sur comment les types sont déterminés, qu'est-ce qu'une fonction polymorphe, etc. Des trucs sans doute de base mais sur lesquels je ne m'étais jamais trop interrogé.

    Du coup, je ne sais pas trop s'il y a des trucs à ajouter. Je mets le sujet en résolu !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 04/03/2013, 11h16
  2. Réponses: 8
    Dernier message: 08/06/2006, 17h05
  3. [Fortran 90] Nombre variable d'arguments
    Par Zoera dans le forum Fortran
    Réponses: 2
    Dernier message: 08/03/2005, 13h08
  4. Procédure avec un nombre variable d'arguments
    Par charly dans le forum Langage
    Réponses: 15
    Dernier message: 21/06/2002, 11h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo