[gull] Faut-il réhabiliter Perl comme langage de scripting système?
Daniel Cordey
dc at pxcluster.com
Sat Mar 10 01:07:41 CET 2018
On 09. 03. 18 23:58, Marc SCHAEFER wrote:
> En fait, ce qui pose aussi problème, c'est la pollution de l'espace de
> nommage. Mais pas en Perl, du moins pas avec les modules propres de
> CPAN. Chaque module a son "namespace".
Il me semble que c'est aussi le cas d'autres langages de scripting; en
tout cas Python. Les programmes de 'lint' peuvent s'avérer utiles pour
débusquer les flemmards :-) En général, il est possible de voir ce qui a
été défini à l'extérieur du "namespace" (un seul niveau), mais une
définition "intérieure" ne peut être exportée à moins de le faire
explicitement et cette variable doit aussi avoir été instanciée
préalablement dans le "namespace" extérieure. C'est un tout cas vrai
pour Python et il me semble aussi en PHP (me souvient plus trop...).
Ce sont les mauvaises pratiques de ceux qui programment qui sont
répréhensibles, pas forcément les langages.
> Je pense que c'est une des forces (et un des dangers de Perl), de pouvoir
> déterminer en fonction du contexte si l'on est en "liste" (tableau) ou en
> scalaire.
C'est le mot "déterminer" qui me gène. On décide que... or, dans un
langage ou tout est un objet (comme Python), l'assignation d'un objet à
une variable va déterminer le type de cette dernière. C'est la fameuse
opposition du "Duck Typing" par rapport à la notion de
déclaration-définition dans les langages "static" fortement typés
(C/C++, Java, etc.)
> Perl permet de faire ça:
>
> my $variable = appel_fonction();
>
> ainsi que
>
> my @variable = appel_fonction();
Je trouve que c'est troublant... à mes yeux, c'est le type retourné par
appel_fonction() qui devrait "déterminer" quel sera le type de
"variable". Donc, si ma fonction me retourne un scalaire ou une liste,
ma variable aura exactement ce type là. Naturellement, le programmeur
Perl aura moins tendance à faire un "for" sur une variable préfixée '$',
mais si la fonction a retourné une liste plutôt qu'un scalaire, nous
aurons aussi une erreur. On a simplement déplacé l'endroit où l'erreur
se produira.
La tendance actuelle est d'introduire plus de possibilité de contrôle en
amont, pour éviter les erreurs à l'exécution. Ceci est bien visible avec
les initiatives PEP de Python, comme :
https://www.python.org/dev/peps/pep-0362/
Les langages duck-typing essayent de se rapprocher des langages à
définition "static", et les langages essaient d'introduire de la
souplesse :-)
Oui, Perl permet beaucoup de choses, et c'est peut-être aussi ce qui le
rend plus difficile à maintenir, et donc moins attractif pas les temps
qui cours.
> Dans d'autres langages, il faut explicitement dire que l'on retourne un
> tableau, de mémoire en PHP c'est le mot-clé list, ou alors passer par des
> références ou des structures complexes.
Justement, dans un langage fortement typé il me semble plus judicieux de
rendre la "source" comme type primaire. Si ma fonction retourne une
liste, je dois manipuler ce qu'elle renvoie comme une liste. Décider à
la réception des données que le type n'est pas ce que l'on veut me
semble moins intuitif car cela peut induire en erreur. Si je désire
assigner un type particulier à ma variable, je veux avoir le choix de le
faire de manière explicite et non restrictive et sans limite; avec des
fonctions de type int(), str(), tuple(), etc. Si cela n'est pas
possible, l'erreur pointera exactement sur cette opération et ne sera
pas décalée ailleurs dans le code.
>
> Autre exemple, prendre des bouts de tableaux:
>
> $tableau[5] représente le 6e élément; @tableau[5..7] un sous-tableau
> de 5 à 7.
>
> D'autres langages ont des fonctions complexes pour faire la même chose,
> le $ désigne un résultat scalaire et le @ un résultat liste (tableau).
Tous les langages n'ont pas forcément ces restrictions. SI je reprends
l'exemple en Python, je peux écrire :
variable = tableau[5]
variable = tableau[5 : 20 : 2]
Où, la première ligne extrait l'objet en 5ème position de 'tableau'. Le
type de variable sera alors celui du cinquième élément du tableau. Or,
il se pourrait très bien que ce cinquième élément soit un... tableau, ou
un dictionnaire, ou un fichier, etc. Je ne suis donc pas restreint à
prédéfinir le type de l'assignation.
Dans la deuxième ligne, on assigne à 'variable' une nouvelle liste des
éléments de 'tableau' compris entre 5 et 20, pas pas de 2.
Il ne s'agit donc pas, à mon avis, de fonctions très complexes.
> Autre exemple, en Perl, je peux écrire:
>
> my @tableau = (@tab1, @tab2, @tab3);
>
> et il est immédiatement évident que l'on veut concaténer le contenu des 3
> tableaux. Dans certains langages on obtiendra un tableau 2D, ou une
> structure complexe avec des références de tableaux.
Je reconnais là que Perl est parfaitement logique dans sa syntaxe :-)
Remarque que je ne me souviens plus trop en PHP, mais en Python tu écrisy :
tableau = tab1 + tab2 + tab3
Pas très cryptique non-plus ?
Je reconnais que, les limitations à traiter des variables plus subtiles
que de simples scalaires en shell, pousse logiquement les gens vers
Perl. Perl étant beaucoup plus puissant ça se défend. Toutefois, lorsque
tu as pratiqué Python de manière fréquente, et que tu as bien compris la
puissance des objets en Python (surcharge de tous les opérateurs,
multi-héritage, etc.), il t'es plus difficile de revenir à Perl à cause
de sa syntaxe (entre autre).
Perl fait le boulot, mais je ne le prendrais pas comme langage
didactique... à moins d'être chargé d'enseigner le "code obfuscating" :-)
> D'un autre côté, cela peut créer des problèmes, exemple:
>
> # validons que le paramètre de formulaire
> # colours est un entier.
> my $scalar = $query->param('colours');
> if ($scalar =~ /^\d+$/) {
> # BUGS
> # - si $query->param('colours') est un
> # paramètre multi-valué, on n'aura
> # validé que le 1er élément du tableau,
> # alors qu'on passe le tableau entier
> # à do_something()
> do_something($query->param('colours'));
> }
>
> NB: j'ai exprès mis une variable scalaire temporaire, mais si on l'enlève
> la sémantique est la même: dans le premier cas, quand on applique la regexp
> on est en contexte scalaire et dans le deuxième en contexte liste.
try :
do_something(int(query.param('colours')))
except ValueError as e :
print("Hey, you're kidding me : {}".format(e))
dc
More information about the gull
mailing list