Discussion:
Translate Unbounded_String paramétré.
(trop ancien pour répondre)
Blady
2019-11-11 17:26:01 UTC
Permalink
Bonjour,

Je cherchais une procédure remplaçant un caractère par un autre dans une
chaine Unbounded_String. Je n'ai trouvé que pour un seul caractère de la
chaine :

procedure Replace_Element (Source : in out Unbounded_String;
Index : in Positive;
By : in Character);

Bon pour toute la chaine il suffit d'itérer...

Ah je met la main sur la procédure qui pourrait faire l'affaire :
procedure Translate (Source : in out Unbounded_String;
Mapping : in Maps.Character_Mapping_Function);

avec par exemple la fonction :
function Arobase_En_Espace (From : Character) return Character is
begin
if From = ' ' then
return '@';
else
return From;
end if;
end Arobase_En_Espace;

j'écris :
Translate (CH1, Arobase_En_Espace'Access);

Ok mais j'aimerais paramétrer le caractère à remplacer et celui de
remplacement :

procedure Translate
(Source : in out Unbounded_String;
De, Vers : Character)
is
function De_En_Vers (From : Character) return Character is
begin
if From = De then
return Vers;
else
return From;
end if;
end De_En_Vers;
begin
Translate (Source, De_En_Vers'Access);
end Translate;

Patatras :
essaitranslate.adb:23:26: subprogram must not be deeper than access type

Est-il possible de s'en sortir sans aller jusqu'à créer un paquetage
générique ou utiliser l'attribut Unrestricted_Access ?

Merci pour vos réponses, Pascal.
http://blady.pagesperso-orange.fr
J-P. Rosen
2019-11-12 06:32:49 UTC
Permalink
Post by Blady
Bonjour,
Je cherchais une procédure remplaçant un caractère par un autre dans une
chaine Unbounded_String. Je n'ai trouvé que pour un seul caractère de la
procedure Replace_Element (Source : in out Unbounded_String;
                              Index  : in Positive;
                              By     : in Character);
Bon pour toute la chaine il suffit d'itérer...
 procedure Translate (Source  : in out Unbounded_String;
                        Mapping : in Maps.Character_Mapping_Function);
function Arobase_En_Espace (From : Character) return Character is
begin
   if From = ' ' then
   else
      return From;
   end if;
end Arobase_En_Espace;
   Translate (CH1, Arobase_En_Espace'Access);
Ok mais j'aimerais paramétrer le caractère à remplacer et celui de
   procedure Translate
     (Source   : in out Unbounded_String;
      De, Vers : Character)
   is
      function De_En_Vers (From : Character) return Character is
      begin
         if From = De then
            return Vers;
         else
            return From;
         end if;
      end De_En_Vers;
   begin
      Translate (Source, De_En_Vers'Access);
   end Translate;
essaitranslate.adb:23:26: subprogram must not be deeper than access type
Est-il possible de s'en sortir sans aller jusqu'à créer un paquetage
générique ou utiliser l'attribut Unrestricted_Access ?
Il suffit de mettre la fonction De_En_Vers à l'extérieur de Translate
(on ne peut pas passer une fonction locale à un pointeur dont le type
est global, sinon on pourrait appeler une fonction qui n'existe plus).

Ceci dit, le plus simple est d'appeler Translate avec une valeur du type
Character_Mapping.
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr
Blady
2019-11-15 21:10:46 UTC
Permalink
Post by J-P. Rosen
Post by Blady
Bonjour,
Je cherchais une procédure remplaçant un caractère par un autre dans une
chaine Unbounded_String. Je n'ai trouvé que pour un seul caractère de la
procedure Replace_Element (Source : in out Unbounded_String;
                              Index  : in Positive;
                              By     : in Character);
Bon pour toute la chaine il suffit d'itérer...
 procedure Translate (Source  : in out Unbounded_String;
                        Mapping : in Maps.Character_Mapping_Function);
function Arobase_En_Espace (From : Character) return Character is
begin
   if From = ' ' then
   else
      return From;
   end if;
end Arobase_En_Espace;
   Translate (CH1, Arobase_En_Espace'Access);
Ok mais j'aimerais paramétrer le caractère à remplacer et celui de
   procedure Translate
     (Source   : in out Unbounded_String;
      De, Vers : Character)
   is
      function De_En_Vers (From : Character) return Character is
      begin
         if From = De then
            return Vers;
         else
            return From;
         end if;
      end De_En_Vers;
   begin
      Translate (Source, De_En_Vers'Access);
   end Translate;
essaitranslate.adb:23:26: subprogram must not be deeper than access type
Est-il possible de s'en sortir sans aller jusqu'à créer un paquetage
générique ou utiliser l'attribut Unrestricted_Access ?
Il suffit de mettre la fonction De_En_Vers à l'extérieur de Translate
(on ne peut pas passer une fonction locale à un pointeur dont le type
est global, sinon on pourrait appeler une fonction qui n'existe plus).
Ceci dit, le plus simple est d'appeler Translate avec une valeur du type
Character_Mapping.
Si je met De_En_Vers à l'extérieur de Translate je n'est plus d'accès à
ses paramètres De et Vers :-(
Il ne me vient pas de solution immédiate.
Je me demandais quelle pouvait être l'utilisation pratique de ce
Translate là (hormis le cas trivial d'une translation statique) qui me
semblait plus simple que celui-ci :

procedure Translate
(Source : in out Unbounded_String;
De, Vers : Character)
is
CM : constant Character_Mapping :=
To_Mapping (To_Sequence (To_Set (De)), To_Sequence (To_Set
(Vers)));
begin
Translate (Source, CM);
end Translate;

Cordialement, Pascal.
Blady
2019-12-07 06:45:20 UTC
Permalink
Post by Blady
Post by J-P. Rosen
Post by Blady
Bonjour,
Je cherchais une procédure remplaçant un caractère par un autre dans une
chaine Unbounded_String. Je n'ai trouvé que pour un seul caractère de la
procedure Replace_Element (Source : in out Unbounded_String;
                               Index  : in Positive;
                               By     : in Character);
Bon pour toute la chaine il suffit d'itérer...
  procedure Translate (Source  : in out Unbounded_String;
                         Mapping : in Maps.Character_Mapping_Function);
function Arobase_En_Espace (From : Character) return Character is
begin
    if From = ' ' then
    else
       return From;
    end if;
end Arobase_En_Espace;
    Translate (CH1, Arobase_En_Espace'Access);
Ok mais j'aimerais paramétrer le caractère à remplacer et celui de
    procedure Translate
      (Source   : in out Unbounded_String;
       De, Vers : Character)
    is
       function De_En_Vers (From : Character) return Character is
       begin
          if From = De then
             return Vers;
          else
             return From;
          end if;
       end De_En_Vers;
    begin
       Translate (Source, De_En_Vers'Access);
    end Translate;
essaitranslate.adb:23:26: subprogram must not be deeper than access type
Est-il possible de s'en sortir sans aller jusqu'à créer un paquetage
générique ou utiliser l'attribut Unrestricted_Access ?
Il suffit de mettre la fonction De_En_Vers à l'extérieur de Translate
(on ne peut pas passer une fonction locale à un pointeur dont le type
est global, sinon on pourrait appeler une fonction qui n'existe plus).
Ceci dit, le plus simple est d'appeler Translate avec une valeur du type
Character_Mapping.
Si je met De_En_Vers à l'extérieur de Translate je n'est plus d'accès à
ses paramètres De et Vers :-(
Il ne me vient pas de solution immédiate.
Je me demandais quelle pouvait être l'utilisation pratique de ce
Translate là (hormis le cas trivial d'une translation statique) qui me
   procedure Translate
     (Source   : in out Unbounded_String;
      De, Vers :        Character)
   is
      CM : constant Character_Mapping :=
        To_Mapping (To_Sequence (To_Set (De)), To_Sequence (To_Set
(Vers)));
   begin
      Translate (Source, CM);
   end Translate;
Une autre possibilité serait d'avoir des sous-programmes génériques
paramétrés par la fonction Character_Mapping_Function au lieu d'un
'Access, par exemple avec Translate:

generic
with function Character_Mapping_Function (From : Character)
return Character;
procedure Translate (Source : in out Unbounded_String);

procedure Translate2 (Source : in out Unbounded_String; De, Vers :
Character) is
function De_En_Vers (From : Character) return Character is
begin
if From = De then
return Vers;
else
return From;
end if;
end De_En_Vers;
procedure My_Translate is new Translate (De_En_Vers);
begin
My_Translate (Source);
end Translate2;

Cela me semble plus utilisable sous cette forme.
Serait-il possible d'ajouter cette forme dans Ada.Strings.Unbounded ?

Merci, Pascal.
J-P. Rosen
2019-12-07 07:15:05 UTC
Permalink
Post by Blady
Une autre possibilité serait d'avoir des sous-programmes génériques
paramétrés par la fonction Character_Mapping_Function au lieu d'un
   generic
      with function Character_Mapping_Function (From : Character) return
Character;
   procedure Translate (Source : in out Unbounded_String);
Character) is
      function De_En_Vers (From : Character) return Character is
      begin
         if From = De then
            return Vers;
         else
            return From;
         end if;
      end De_En_Vers;
      procedure My_Translate is new Translate (De_En_Vers);
   begin
      My_Translate (Source);
   end Translate2;
Cela me semble plus utilisable sous cette forme.
Personnellement, je préfère les génériques aux pointeurs sur
sous-programmes, en particulier parce qu'on n'a jamais de problème de
niveau d'accessibilité.
Post by Blady
Serait-il possible d'ajouter cette forme dans Ada.Strings.Unbounded ?
Il ne suffit pas d'avoir une bonne idée pour modifier un standard. Il
faut aussi montrer un besoin réel et important qui ne pourrait pas être
satisfait autrement.

Je crains que ce ne soit pas le cas ici...
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr
Loading...