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 :

Stream.from et le 'a option


Sujet :

Caml

  1. #1
    Membre à l'essai
    Inscrit en
    Novembre 2004
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 13
    Points : 11
    Points
    11
    Par défaut Stream.from et le 'a option
    Désolé, c'est de nouveau moi avec à nouveau une erreur certainement bête.
    J'aimerai utiliser Stream.from mais je n'y arrive pas à cause à priori d'un problème de typage avec la fonction que l'on doit passer en paramètre.

    Voici l'erreur exacte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    This expression has type int -> Token.token but is here used with type
      int -> 'a option
    D'après ce que j'ai compris sur les signatures des fonctions, la signature demandée par Stream.from est une fonction qui prend un paramètre un entier et retourne n'importe quel type (mais le même à chaque appel).

    Je pensais que c'était peut-être à cause de mon type token mais j'ai fait l'essai avec une fonction ayant pour signature int->int et le problème est le même.

    Le 'a n'est pas un paramètre "générique" ??

  2. #2
    alex_pi
    Invité(e)
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    val from : (int -> 'a option) -> 'a t
    Stream.from f returns a stream built from the function f. To create a new stream element, the function f is called with the current stream count. The user function f must return either Some <value> for a value or None to specify the end of the stream.
    (lu sur http://caml.inria.fr/pub/docs/manual...ef/Stream.html)

    Il faut que la fonction soit de type (int -> 'a option), pas (int -> 'a) ! C'est à dire qu'elle retourne soit None soit Some xx est de type 'a.

    Je peux me permettre de te demander comment tu apprends Caml ? J'avoue ne pas être convaincu qu'attaquer les streams quand on ne maitrise pas dutout les types de base de Caml (comme le type option) soit judicieux.

  3. #3
    Membre à l'essai
    Inscrit en
    Novembre 2004
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    Merci.
    J'ai fini par renvoyer Some(la valeur).

    Sinon c'est en fait un projet que l'on devrait normalement faire en C qui consiste à faire une compilation d'un sous ensemble de Pascal -> P-Code puis une interprétation du P-Code. J'ai envie d'essayer de le faire en OCaml parce que j'ai lu plein de bonne choses sur lui, en particulier pour ce domaine de compilation / interprétation. Du coup j'apprend le langage au fur et à mesure aussi. J'ai bien un livre nommé "Apprentissage de la programmation avec OCaml" que j'ai emprunté dans notre bibliothèque mais je le lis au coup par coup quand j'ai le temps.

    C'est pour cela que j'ai encore de gros problèmes de syntaxe et du langage en particulier.

    Si vous avez des liens sur des tutoriels qui abordent un peu tous les aspects de OCaml mais de facons synthétique, je suis preneur. Pareil pour des livres.

    En tout cas merci, ca me permet de continuer à avancer.

  4. #4
    alex_pi
    Invité(e)
    Par défaut
    J'ai personnellement bien aimé "Développement d'application avec Objective Caml", mais en moins cher, il y a des tutoriaux sur ce site
    http://gorgonite.developpez.com/tuto.../introduction/
    http://damien-guichard.developpez.com/tutoriels/ocaml/

    En revanche, je ne suis pas sûr que tu sois obligé de faire des streams pour écrire un parseur/interpréteur. Des outils comme ocamlyacc ou menhir donnent des résultats fort sympathique (je n'ai jamais été un grand fan de passer du temps sur le parsage (vilain néologisme) alors que tout ce qui suit est tellement plus intéressant !)

  5. #5
    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

  6. #6
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par bluestorm Voir le message
    Effectivement, j'avais oublié qu'il était disponible. Mais je préfère quand même avoir une version papier (quand c'est long, je lis mieux sur papier que sur écran personnellement), et là, c'est loin d'être donné :-)

  7. #7
    Membre à l'essai
    Inscrit en
    Novembre 2004
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    Merci pour tous ces liens.

  8. #8
    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 991
    Points
    2 991
    Par défaut
    C'est certain l'analyse lexicale/syntaxique est sémantiquement totalement creuse, donc on peut considérer ça comme le sale boulot. Cependant il faut bien le faire, que ça plaise ou non, car depuis le temps qu'on nous promet la programmation 100% graphique on s'est habitué au texte au point que maintenant l'avenir c'est l'unicode.

    Je ne connais que trois façons de faire:
    • avec un méta-outil Yacc/Bison/Menhir
    • avec une librairie (qui sait où trouver la pcl?)
    • à la main façon Niklaus-Wirth


    Je vais bientôt écrire une partie dédiée à ce sujet dans mon tutoriel.
    Voici du code préliminaire (incomplet et pas testé) qui effleure la problématique:

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    module Lex = struct
     
    type server =
      {
      (* demands *)
      demand_line   : unit   -> unit;
      demand_word   : string -> unit;
      demand_char   : char   -> unit;
      demand_name   : unit   -> string;
      demand_int    : unit   -> int;
      (* promises *)
      promised_name : unit   -> bool;
      promised_int  : unit   -> bool;
      (* grants *)
      granted_word  : string -> bool;
      granted_char  : char   -> bool;
      (* more *)
      promised_word : string -> bool;
      promised_char : char   -> bool;
      }
     
    type lexical  = A_word | A_char | A_num
    type position = {line: int; text: string; start: int; stop: int}
     
    type demand =
      | Word of position * string
      | Char of position * char
      | Name of position
      | Int  of position
     
    exception Denied of demand
     
    let make file =
      let str = ref ""
      and len = ref 0
      and row = ref 0
      and   l = ref 0
      and   r = ref 0
      and num = ref 0
      and lex = ref A_char
      and deny demand =
        raise (Denied demand)
      in let locate () =
        {line = !row; text = !str; start = !l; stop = !r}
      and same_word s =
        if String.length s = !r - !l then
          let a = ref 0 and b = ref !l in
          while !b < !r && s.[!a] = !str.[!b] do incr a; incr b done;
          !b = !r
        else
          false
      and read_row () =
        str := input_line file;
        len := String.length !str;
        incr row; l := 0; r := 0
      in let blank_space c =
        if !r < !len then (c=' ' or c='\t')
        else (read_row (); true)
      and upper_lower c =
        (!r < !len) && (c>='a' && c<='z' or c>='A' && c<='Z') 
      and alpha_num c =
        (!r < !len) &&
        (c>='a' && c<='z' or c>='A' && c<='Z' or c='_' or c>='0' && c<='9')
      and ascii_num c =
        (!r < !len) && (c>='0' && c<='9')
      in let read_next () =
        while blank_space !str.[!r] do incr r done;
        l := !r;
        lex := match !str.[!r] with
        | c when upper_lower c ->
            while alpha_num !str.[!r] do incr r done;
            A_word  
        | c when ascii_num c ->
            num := 0;
            while ascii_num !str.[!r] do
              let d = int_of_char !str.[!r] - int_of_char '0'
              in  num := !num * 10 + d;
              incr r
            done;
            A_num
        | c ->
            incr r;
            A_char
      in
      (* demands *)
      let demand_line () =
        read_row (); read_next ()
      and demand_word s =
        match !lex with
        | A_word when same_word s -> read_next ()
        | _ -> deny (Word(locate(),s))
      and demand_char c =
        match !lex with
        | A_char when !str.[!l]=c -> read_next ()
        | _ -> deny (Char(locate(),c))
      and demand_name () =
        match !lex with
        | A_word -> let s = String.sub !str !l (!r - !l) in read_next (); s
        | _ -> deny (Name(locate()))
      and demand_int () =
        match !lex with
        | A_num -> let n = !num in read_next (); n 
        | _ -> deny (Int(locate()))
      (* promises *)
      and promised_name () =
        !lex = A_word 
      and promised_int () =
        !lex = A_num 
      (* grants *)
      and granted_word s =
        match !lex with
        | A_word when same_word s -> read_next (); true
        | _ -> false
      and granted_char c =
        match !lex with
        | A_char when !str.[!l]=c -> read_next (); true
        | _ -> false
      (* more *)
      and promised_word s =
        !lex = A_word && same_word s
      and promised_char c =
        !lex = A_char && !str.[!l]=c
      in
      demand_line ();
      {
      (* demands *)
      demand_line   = demand_line;
      demand_word   = demand_word;
      demand_char   = demand_char;
      demand_name   = demand_name;
      demand_int    = demand_int;
      (* promises *)
      promised_name = promised_name;
      promised_int  = promised_int;
      (* grants *)
      granted_word  = granted_word;
      granted_char  = granted_char;
      (* more *)
      promised_word = promised_word;
      promised_char = promised_char;
    }
     
    end;;
    Une fois invoqué le constructeur make, l'interface du type Lex.server propose 3 sortes d'opérations:
    • demand_ exige un certain article et provoque une erreur en cas d'échec, en cas de succès on passe à l'article suivant
    • promissed_ interroge la présence d'un certain article, ne passe jamais à l'article suivant
    • granted_ interroge la présence d'un certain article, passe à l'article suivant en cas de succès


    À mon avis le type stream est plus laborieux que la fonction input_line.

  9. #9
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par SpiceGuid Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
      (* demands *)
      demand_line   : unit   -> unit;
      demand_word   : string -> unit;
      demand_char   : char   -> unit;
      demand_name   : unit   -> string;
      demand_int    : unit   -> int;
    Euh... Pourquoi demand_int et demand_char ont des signatures totalement différentes ?

  10. #10
    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 991
    Points
    2 991
    Par défaut
    • demand_int () tu demandes une constante entière, tu obtiens sa valeur. sinon tu provoques une exception. si tu n'es pas certain de la présence d'un entier tu peux interroger à l'aide de promised_int ().
    • demand_char ';' tu demandes un point-virgule. en cas d'absence tu provoques une exception.


    Les noms ne sont pas basés sur les types mais sur le comportement vis-à-vis de l'échec et du passage à l'article suivant.

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

Discussions similaires

  1. internet video stream from shell
    Par frp31 dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 29/01/2011, 21h29
  2. Streaming from ftp avec Libcurl, openal, ffmpeg
    Par yipyop31 dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 27/04/2010, 12h49
  3. [ImageIO.read] Can't get input stream from URL!
    Par el_mosquito dans le forum Servlets/JSP
    Réponses: 5
    Dernier message: 12/09/2007, 15h55
  4. Réponses: 10
    Dernier message: 31/05/2006, 17h15

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