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

        

_______________________________________________
gull mailing list
[email protected]
http://forum.linux-gull.ch/mailman/listinfo/gull

Répondre à