[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