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 :

Pattern matching dynamique


Sujet :

Caml

  1. #1
    Membre habitué
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Points : 190
    Points
    190
    Par défaut Pattern matching dynamique
    Je me demandais s'il existe un moyen de faire du pattern matching configurable à l’exécution plutôt qu'à la compilation

    par exemple à la compilation on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    let handle item = match item with
       | 1 -> "Do this";
       | 2 -> "Do that";
       | n -> "Do Nothing";
    ;;
    j'aimerais pouvoir faire un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let list = [(1, "Do this\n"); (2, "Do that\n")];;
     
    let handle l =
    let rec rhandle l = match l with
       | [] -> "Empty list"
       | (i, s)::rest -> print_string s; rhandle rest
       | (n, s)::rest -> "Do Nothing" in
     
    rhandle l
    ;;
     
    handle list;;
    pour qu'à chaque entier d'un couple, la chaine associée soit affichée (ou la même chose mais avec une fonction)

    de façon plus élégante et standard évidemment

    ou même mieux, pouvoir paramétrer le type de i et que la pattern matching détermine automatiquement ce que c'est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
     
    type items = itemA | itemB;; 
     
    let list = [(itemA, "itemA\n"); (itemB, "itemB\n")];;
     
    let handle l =
    let rec rhandle l = match l with
       | [] -> "Empty list"
       | (i : items, s)::rest -> print_string s; rhandle rest
       | (n, s)::rest -> "Do Nothing" in
     
    rhandle l
    ;;
     
    handle list;;
    en fait mon but est d'émuler le pattern chaine de responsabilité mais avec les avantages syntaxiques d'Ocaml

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Je n'ai pas compris ce que tu veux, à part la fin "chaîne de responsabilité".

    Du coup j'ai écrit un peu de code pour faire un truc qui ressemble, mais je ne sais pas si ça correspond à ce que tu demandes, vu que je n'ai pas bien compris ce que tu voulais.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    type ('a, 'b) decision =
      | PassNext of 'a
      | Return of 'b
     
    let rec eval handlers arg = match handlers with
      | [] -> failwith "no handlers"
      | h::rest ->
        match h arg with
          | Return ret -> ret
          | PassNext new_arg -> eval rest new_arg
     
    let filter cond handler = fun arg ->
      if cond arg then handler arg else PassNext arg
     
    let passnext f = fun arg -> PassNext (f arg)
    let return f = fun arg -> Return (f arg)
     
    let watcher name = fun arg ->
      Printf.printf "%s: saw %d\n" name arg;
      PassNext arg
     
    let () =
      let handlers = [
        watcher "h1";
        filter (fun n -> n mod 2 = 0) (watcher "h2");
        filter (fun n -> n > 10) (return ((+) 2));
        passnext ((+) 1);
        watcher "h3";
        return (fun _ -> 0);
      ] in
      let test arg =
        print_endline "eval...";
        let result = eval handlers arg in
        Printf.printf "result: %d\n\n" result in
      test 3;
      test 4;
      test 21

  3. #3
    Membre habitué
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Points : 190
    Points
    190
    Par défaut
    Citation Envoyé par gasche Voir le message
    Je n'ai pas compris ce que tu veux, à part la fin "chaîne de responsabilité".

    Du coup j'ai écrit un peu de code pour faire un truc qui ressemble, mais je ne sais pas si ça correspond à ce que tu demandes, vu que je n'ai pas bien compris ce que tu voulais.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    type ('a, 'b) decision =
      | PassNext of 'a
      | Return of 'b
     
    let rec eval handlers arg = match handlers with
      | [] -> failwith "no handlers"
      | h::rest ->
        match h arg with
          | Return ret -> ret
          | PassNext new_arg -> eval rest new_arg
     
    let filter cond handler = fun arg ->
      if cond arg then handler arg else PassNext arg
     
    let passnext f = fun arg -> PassNext (f arg)
    let return f = fun arg -> Return (f arg)
     
    let watcher name = fun arg ->
      Printf.printf "%s: saw %d\n" name arg;
      PassNext arg
     
    let () =
      let handlers = [
        watcher "h1";
        filter (fun n -> n mod 2 = 0) (watcher "h2");
        filter (fun n -> n > 10) (return ((+) 2));
        passnext ((+) 1);
        watcher "h3";
        return (fun _ -> 0);
      ] in
      let test arg =
        print_endline "eval...";
        let result = eval handlers arg in
        Printf.printf "result: %d\n\n" result in
      test 3;
      test 4;
      test 21
    je ne comprend pas trop à quoi servent passnext et return

    EDIT : ah ok return stoppe l'évaluation et passnext passe au suivant

    bon ça correspond à ce que je demandais, une liste de handlers-conditions qui catchent ou non un argument (chaine de responsabilité)

    par contre est-ce qu'il possible de filtrer selon le type de l'argument ?

    par ex si j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type event = EventA |EventB
    et que je veux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    filter (fun event -> event of EventA) (watcher "EventA");
    filter (fun event -> event of EventB) (watcher "EventB");
    comment m'y prendre ?

    niveau performances, c'est plus lent qu'un pattern matching classique ?

  4. #4
    Membre actif
    Avatar de Ptival
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2004
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2004
    Messages : 70
    Points : 276
    Points
    276
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    isEventA = function EventA -> true | _ -> false
    isEventB = function EventB -> true | _ -> false
     
    [...]
     
    filter isEventA (watcher "EventAhandler");

  5. #5
    Membre habitué
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Points : 190
    Points
    190
    Par défaut
    Citation Envoyé par Ptival Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    isEventA = function EventA -> true | _ -> false
    isEventB = function EventB -> true | _ -> false
     
    [...]
     
    filter isEventA (watcher "EventAhandler");
    ok, merci

    il y a un autre situation qui me chiffonne : une hiérarchie de variants

    mettons que j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    type subEvent=
    	| EventA
    	| EventB
    ;;
     
    type event = 
    	| EventAA of EventA
    	| EventBB of EventB
    ;;
    vu que dans une liste on ne peut placer que des éléments de même type, je ne pourrai pas mettre au même niveau un subEvent et un event

  6. #6
    Membre actif
    Avatar de Ptival
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2004
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2004
    Messages : 70
    Points : 276
    Points
    276
    Par défaut
    Je crois que la solution "ad hoc" et "simple" est de les envelopper dans un type somme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    type events =
    | Event of event
    | SubEvent of subEvent
    et de créer une liste d'Une solution plus "avancée" consisterait à exploiter les variants polymorphes, je pense, mais je ne suis pas certain que ce soit la bonne solution (je laisse aux autres le soin de compléter).

Discussions similaires

  1. Pattern Matching sur une InputStream?
    Par Phoxtrot dans le forum Général Java
    Réponses: 2
    Dernier message: 19/05/2008, 15h36
  2. Use of uninitialized value in pattern match (m//)
    Par Vladkergan dans le forum Langage
    Réponses: 4
    Dernier message: 13/01/2008, 20h25
  3. pattern matching (image processing)
    Par anatore dans le forum Traitement d'images
    Réponses: 8
    Dernier message: 15/10/2007, 17h01
  4. Use of uninitialized value in pattern match(m//)
    Par hayaet dans le forum Langage
    Réponses: 1
    Dernier message: 08/10/2007, 12h45
  5. [Regex] Pattern matching
    Par jeRame dans le forum Collection et Stream
    Réponses: 1
    Dernier message: 26/06/2007, 15h28

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