OVH Cloud OVH Cloud

eval

14 réponses
Avatar
Nicolas
Bonjour,

eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1
}
} ;

fait exactement ce dont j'ai besoin, mais

$formule = '${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1' ;
eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
$formule
}
} ;

ne fait rien, même pas un message d'erreur. Pourquoi ?

Merci. Nicolas.

--
Powered .~.
by Linux /V\ Enlever
------ // \\ Take off
solutions for /( )\ BULBA
smart penguins ^`~'^

10 réponses

1 2
Avatar
Paul Gaborit
À (at) Mon, 16 Jan 2006 12:41:16 +0100,
Nicolas écrivait (wrote):
eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1
}
} ;

fait exactement ce dont j'ai besoin, mais

$formule = '${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1' ;
eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
$formule
}
} ;

ne fait rien, même pas un message d'erreur. Pourquoi ?


La fonction 'eval' a deux modes de fonctionnement totalement
différents.

Dans celui que vous utilisez, le code est fourni sous la forme d'un
bloc (entre accolades). Ce code est compilé lors la compilation du
script lui-même et c'est donc du code normal. Ce mode est surtout
utile pour capter les erreurs (ou exceptions).

Dans le second mode, le code est fourni sous la forme d'une chaîne de
caractères. Ce code est compilé puis exécuté à chaque exécution de
l'instruction 'eval'. Le code peut donc changer... C'est quand même
plus lent que le premier mode. De plus, dans la plupart des cas et
comme les références symboliques, ce mode est souvent utilisé alors
qu'on aurait pu passer par des mécanismes plus efficaces ou sûrs
(références non symboliques, sub anonymes, fermetures, etc.).

Donc :

eval { ... };

n'est pas la même chose que :

eval "....";

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Nicolas

Bonjour,

eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1
}
} ;



Essaye :

eval 'for (my $i = 0 ; $i < $nb_fois ; $i++) {'."$formule".'}' ;

Merci. Nicolas.


Mais de rien ;-))


--
Powered .~.
by Linux /V Enlever
------ // Take off
solutions for /( ) BULBA
smart penguins ^`~'^

Avatar
Nicolas
À (at) Mon, 16 Jan 2006 12:41:16 +0100,
Nicolas écrivait (wrote):

eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1
}
} ;

fait exactement ce dont j'ai besoin, mais

$formule = '${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1' ;
eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
$formule
}
} ;

ne fait rien, même pas un message d'erreur. Pourquoi ?



La fonction 'eval' a deux modes de fonctionnement totalement
différents.

Dans celui que vous utilisez, le code est fourni sous la forme d'un
bloc (entre accolades). Ce code est compilé lors la compilation du
script lui-même et c'est donc du code normal. Ce mode est surtout
utile pour capter les erreurs (ou exceptions).


...

Merci pour ces explications.
J'ai fini par comprendre que j'avais mélangé les deux mode et que l'eval
de mon exemple ne voyait jamais le code de $formule. J'ai donc tout mis
dans une seule chaîne.

Merci encore.

Nicolas.

--
Powered .~.
by Linux /V Enlever
------ // Take off
solutions for /( ) BULBA
smart penguins ^`~'^


Avatar
Paul Gaborit
À (at) Mon, 16 Jan 2006 15:41:46 +0100,
Nicolas écrivait (wrote):
J'ai fini par comprendre que j'avais mélangé les deux mode et que
l'eval de mon exemple ne voyait jamais le code de $formule. J'ai donc
tout mis dans une seule chaîne.


Donc, la bonne question à se poser maintenant est « Pourquoi ai-je
besoin d'un 'eval' sous cette forme ? ».

Et, dans 99% des cas, la réponse sera « En fait, en concevant
correctement mon programme, je n'en ai pas besoin. ».

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Nicolas

Donc, la bonne question à se poser maintenant est « Pourquoi ai-je
besoin d'un 'eval' sous cette forme ? ».

Et, dans 99% des cas, la réponse sera « En fait, en concevant
correctement mon programme, je n'en ai pas besoin. ».


Je pense être dans le 1% restant ;-))

J'utilise actuellement perl pour faire une sorte de tableur allégé sous
latex. Par exemple :

La commande latex SplitListe[nom=A]{0} va mettre la $A[0]=0

la commande latex RempRec[nom=A,i={0:1:10}]{A[i+1]=A[i]+1}

va remplir @A={0,1,2,3,4,5,6,7,8,9,10}

La commande RempRec[nom=B,i={0:1:11}]{B[i]=A[i]**2}

va remplir @B={0,2,4,9,16,25,36,49,64,81,100}

Pour faire ces boucles je crois avoir besoin d'un eval.

Nicolas.

--
Powered .~.
by Linux /V Enlever
------ // Take off
solutions for /( ) BULBA
smart penguins ^`~'^

Avatar
Paul Gaborit
À (at) Mon, 16 Jan 2006 16:44:32 +0100,
Nicolas écrivait (wrote):
Je pense être dans le 1% restant ;-))

J'utilise actuellement perl pour faire une sorte de tableur allégé
sous latex. Par exemple :

La commande latex SplitListe[nom=A]{0} va mettre la $A[0]=0

la commande latex RempRec[nom=A,i={0:1:10}]{A[i+1]=A[i]+1}

va remplir @A={0,1,2,3,4,5,6,7,8,9,10}

La commande RempRec[nom=B,i={0:1:11}]{B[i]=A[i]**2}

va remplir @B={0,2,4,9,16,25,36,49,64,81,100}

Pour faire ces boucles je crois avoir besoin d'un eval.


Je ne pense pas que ce soit obligatoirement nécessaire. Les fermetures
(ou closures en anglais) peuvent faire des choses très intéressantes.
Par exemple, le code suivant :

----------------------------------------
sub gen_boucle {
my ($start, $end) = @_;
return sub {
my $param = shift;
foreach my $i ($start..$end) {
print "$param:$in";
}
}
}

my $boucle1 = gen_boucle(2,3);
my $boucle2 = gen_boucle(4,8);

print "Boucle 1 (2 fois)n";
$boucle1->("a");
$boucle1->("b");
print "Boucle 2n";
$boucle2->("c");
----------------------------------------

affichera la sortie suivante :

----------------------------------------
Boucle 1 (2 fois)
a:2
a:3
b:2
b:3
Boucle 2
c:4
c:5
c:6
c:7
c:8
----------------------------------------

On peut même les utiliser en direct (en utilisant la même sub
'gen_boucle' que ci-dessus) :

gen_boucle(0,1)->("exemple");

qui donne :

----------------------------------------
exemple:0
exemple:1
----------------------------------------

Je ne sais pas comment votre application est conçue mais je pense
qu'en utilisant ces mécanismes couplés à une table de hachages pour
l'espace de nommage (exactement comme fait Perl en interne avec la
table %::), elle doit pouvoir se passer de 'eval "..."'.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Nicolas
Je ne pense pas que ce soit obligatoirement nécessaire. Les fermetures
(ou closures en anglais) peuvent faire des choses très intéressantes.
Par exemple, le code suivant :


C'est très nouveau pour moi et je vais prendre le temps de bien
regarder. Je vous en reparle dans qques jours.

Nicolas.

--
Powered .~.
by Linux /V Enlever
------ // Take off
solutions for /( ) BULBA
smart penguins ^`~'^

Avatar
Nicolas
"Paul Gaborit" a écrit dans le message de
news:

À (at) Mon, 16 Jan 2006 16:44:32 +0100,
Nicolas écrivait (wrote):

Je ne sais pas comment votre application est conçue mais je pense
qu'en utilisant ces mécanismes couplés à une table de hachages pour
l'espace de nommage (exactement comme fait Perl en interne avec la
table %::), elle doit pouvoir se passer de 'eval "..."'.

#######################################

Si j'ai bien compris il faut quand même avoir une base commune à une
fermeture.
Dans les exemple tu propose de créer dynamiquement des boucles ce qui est
déjà intéressant mais ma commande nécessite aussi d'avoir le contenu
dynamique dans la bloucle, par exemple des chose comme

$A[$i+1]=$A[$i] + 1

$B[$i]=$A[$i] **2 pour les deux exemples que j'ai donnés,

La même commande doit pouvoir faire les deux et toutes les sortes
d'affectation que l'on peut imaginer entre des lignes de tableaur.
Si c'est possible sans eval, je suis preneur mais je ne vois pas comment.

Cette commande pourra même faire deux boucle imbriquées :

dans les paramètre latex : i={1:1:9}, j={0:1:9}

et puis faire faire $A[$j][$i]=$j*10 + $i

Si tu peux avoir la gentillesse de m'expliquer, mais comme l'idée c'est
d'arriver à faire un peu n'importe quoi du point de vu formule, j'ai un
doute. Mais mon expérience en fermeture en nulle ;-)

Merci.

Nicolas.
Avatar
Paul Gaborit
À (at) Tue, 17 Jan 2006 11:27:55 +0100,
"Nicolas" écrivait (wrote):
Dans les exemple tu propose de créer dynamiquement des boucles ce qui est
déjà intéressant mais ma commande nécessite aussi d'avoir le contenu
dynamique dans la bloucle, par exemple des chose comme

$A[$i+1]=$A[$i] + 1

$B[$i]=$A[$i] **2 pour les deux exemples que j'ai donnés,
[...]

Cette commande pourra même faire deux boucle imbriquées :

dans les paramètre latex : i={1:1:9}, j={0:1:9}

et puis faire faire $A[$j][$i]=$j*10 + $i

Si tu peux avoir la gentillesse de m'expliquer, mais comme l'idée c'est
d'arriver à faire un peu n'importe quoi du point de vu formule, j'ai un
doute. Mais mon expérience en fermeture en nulle ;-)


Houlà ! La demande est ici très générale. Les fermetures ne sont
qu'une brique parmi d'autres pour répondre à un tel besoin.

À mon avis, il y a deux approches générales possibles :

1- si on fait une *totale* confiance à la source extérieure de
formules (ici le document LaTeX) et si on veut récupérer *facilement*
toute la puissance de Perl dans ces formules alors le passage par
'eval "..."' est intéressant. Mais il faut bien voir que c'est un trou
de sécurité béant si on utilise cela sur des documents non sûr...

2- si on ne fait pas totalement confiance à la source extérieure de
formules ou si on veut pouvoir limiter les fonctions accessibles à un
sous-ensemble bien déterminé de fonctions Perl ou si la syntaxe
utilisée n'est pas exactement celle de Perl, il faudrait alors passer
par la définition d'une grammaire et d'un parser de cette grammaire
(en utilisant Parse::Yapp ou Parse::RecDescent par exemple). Et dans
ce cas, on peut (on doit même) se passer de 'eval "..."'.

Toutes les approches intermédiaires (entre 1 et 2 qui sont les
extrêmes) sont envisageables. En revanche, en terme de sécurité, la
quasi totalité des approches intermédiaires seront du même niveau que
la solution 1 (c'est à dire non sûre).

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Nicolas George
Paul Gaborit wrote in message :
En revanche, en terme de sécurité, la
quasi totalité des approches intermédiaires seront du même niveau que
la solution 1 (c'est à dire non sûre).


Il y a le package Safe qu'il pourrait être intéressant d'examiner, de ce
point de vue.

1 2