C'est bon j'ai rajouté une solution bonus reprenant ton code!
Version imprimable
C'est bon j'ai rajouté une solution bonus reprenant ton code!
Les parenthèses et une indentation appropriée font généralement l'affaire.
On peut aussi chaîner les ternaires sans entrecroiser les conditons vrai/faux, c'est parfois plus lisible:
Code:result = mysteryNumber <= myNumber ? mysteryNumber == myNumber ? 'Congratulations !' : '-' : '+';
Bon j'ai rajouté une solution mega bonus, y'aura le choix! ;)
Si tout le monde est ok (personne ne dit rien dans l'heure), j'envoie en correction orthographique.
Pour moi c'est toujours bon
Alors vu les balaises qui s'y sont penchés en plus, c'est super mega bon
Bonjour,
J'ai fait la correction orthographique de l'exercice 1.2.5 et j'ai une remarque sur le fond. Je débute sur DVP aussi je ne suis pas sûr d'être au bon endroit pour poster ces commentaires ; si c'est le cas, merci de m'indiquer la marche à suivre.
Puisqu'on s'adresse à des débutants, je pense qu'il serait préférable de ne pas évoquer le fait que l'opérateur puisse être utilisé pour autre chose que retourner une valeur.
Un opérateur combine des valeurs pour en produire une autre, syntaxiquement c'est une expression. Ce n'est donc (pas du tout) équivalent au if...else qui est une instruction. C'est un héritage du langage C que d'autoriser à ignorer une valeur, et donc à utiliser une expression comme instruction (le cas prototypique en C est a = 0, qu'on peut utiliser dans c = b = a = 0;.
Du coup la presque équivalence avec le if...else pourrait être présentée plutôt avec max = x < y ? y : x;
équivalent à :
Code:
1
2
3
4 if (x < y) max = y; else max = x;
Je coupe peut-être les cheveux en quatre et je manque sans doute d'expérience de "vraie" programmation mais il me semble que l'utilisation de l'opérateur ternaire comme instruction doit être assez rare et n'est pas une bonne pratique.
En parler brouille le message sans réel intérêt pratique.
Qu'en dîtes-vous ?
Cordialement,
Damien.
Salut Damien,
C'est bien le bon endroit pour en discuter, mais je ne suis pas sûr de comprendre où tu veux en venir... qu'est-ce que tu suggères comme changement dans la formulation de l'exercice ?
C'est une bonne pratique de limiter l'usage des conditions ternaires à des expressions simples, voire directement des valeurs, pour favoriser la lisibilité.
Bonjour Sylvain,
Voici ci-dessous comment je reformulerais la partie "Cours".
C'est du chipotage mais mon expérience d'enseignant m'incite à penser qu'évoquer la possibilité d'utiliser l'opérateur ternaire pour autre chose que calculer une valeur brouille le message et n'apporte rien à l'exercice finalement.
Cours
L'opérateur ternaire est une notation permettant de retourner une valeur suivant le résultat d'une expression booléenne (à la manière d'un simple if...else). Les deux codes suivants sont équivalents :
Code:
1
2
3
4
5 if (condition) { x = valeur1; } else { x = valeur2; }
Code:x = condition ? valeur1 : valeur2;
Exemple :
Code:console.log(number >= 0 ? '+' : '-'); // Affiche "+" si la variable "number" est positive, sinon "-"
Dans cet exemple, si la variable number est supérieure ou égale à 0, l'expression number >= 0 ? '+' : '-' renvoie + sinon - en argument de la fonction console.log.
On peut imbriquer des conditions ternaires ou les utiliser avec des expressions plus complexes, mais dans ce cas la lisibilité devient souvent inférieure à celle d'une structure if...else.
Effectivement c'est du chipotage :mrgreen: Je ne vois pas non plus ce que l'affectation à une variable x apporte de plus, d'autant qu'on ne fait pas d'affectation dans le code d'exemple. On peut parler d'expression si c'est le mot "instruction" qui t'ennuie.
Limiter les ternaires au calcul de valeur, c'est un peu ambigu. Par exemple si j'écris `J'ai ${n} ${ n == 1 ? "pomme": "pommes"}`, c'est un cas classique et pertinent pour utiliser une condition ternaire. Mais on peut aussi écrire de manière plus générique : `J'ai ${n} ${ n == 1 ? "pomme": getPluralForm("pomme")}`. On a alors une instruction plutôt qu'une valeur déclarée littéralement, mais la ternaire est toujours aussi adéquate.
Autre exemple qui me vient en tête, cette définition très concise de la fonction factorielle :
Il y a donc de nombreuses situations où les conditions ternaires sont appropriées avec des instructions. La seule limite (qui est une recommandation) est celle de la lisibilité, et on a déjà mis un message d'avertissement à ce sujet dans l'exercice:Code:const factorial = n => n < 2 ? 1 : n * factorial(n - 1)
Citation:
On peut imbriquer des conditions ternaires ou les utiliser avec des expressions plus complexes, mais dans ce cas la lisibilité devient souvent inférieure à celle d'une structure if...else.
Re-bonjour,
Oui, je chipote. Mais dans les exemples que tu me donnes, l'opérateur ?: n'est pas utilisé comme instruction, mais bien comme expression. Cela renforce mon avis qu'il faut éviter d'évoquer cette possibilité. C'est juste l'équivalence avec le if-else qui me gêne, l'affectation à une variable était juste un cas particulier mais qui évite de d'indiquer que les 2ème et 3ème arguments de l'opérateur puissent être des instructions. À mon sens on ne peut mettre que des valeurs.
Un exemple d'utilisation comme instruction serait :
Et ça c'est vilain...Code:
1
2
3 x = ... x < 0 ? console;log("X est négatif") : console.log("X est positif ou nul");
Mais je cesse de chipoter.
Je veux bien rédiger un ou deux exercices, peux-tu m'indiquer s'il y des thèmes en attente ?
Merci de ta réactivité en tout cas,
Damien.
Salut,
Pour ma part, j'utilise toujours l'opérateur ternaire comme une expression pour définir une valeur. Cela me semble assez naturel de ne pas l'utiliser comme une instruction et d'ailleurs je ne souviens pas avoir vu beaucoup (pour pas dire aucun) d'exemples en ce sens.
Et donc s'agissant d'un tuto pour débutants je serais plutôt de ton avis concernant l'exemple de base qui devrait plutôt être sous la forme d'une expression pour définir une valeur. D'autant plus que l'on ne présente pas cette forme simple (sauf par l'intermédiaire de console.log) puisque l'exercice porte directement sur l'imbrication de conditions.
A vrai dire une des premières moutures de ce tuto avait une présentation très voisine de ta remarque. Puis une partie cours plus théorique donc plus exhaustive a remplacé la présentation avec l'exemple basique. Sans doute aurions-nous dû garder les deux.
Si mes souvenirs son bons, c'est vermine qui accorde les droits. Ils te seront nécessaires pour voir ici les exercices en cours et à venir. Ta contribution ne sera pas de trop, il reste du travail :)
Quelle différence tu fais entre une expression et une instruction ? C'est juste l'absence d'affectation qui te titille ? J'ai le sentiment qu'il s'agit davantage d'une préférence de style, un peu comme f && f() pour exécuter une fonction potentiellement non définie.
On peut s'accorder sur les préférences de style dans les codes d'exemple des exercices, ça ne veut pas dire pour autant qu'on doit changer le contenu des exercices pour volontairement omettre d'évoquer des cas d'utilisations valides en JavaScript sous prétexte qu'elles ne suivent pas nos préférences de style.
Je comprends l'interrogation de Damien sur l'équivalence car je me suis posé la question. C'est pour cela que j'ai mis une phrase d'introduction que j'espère un minimum explicite.
Comme nous l'avons dis depuis le début, je pense que même si le contenu doit être accessible à un tout jeune débutant cela ne veut pas dire qu'il sera capable d'ingérer 100% des informations que nous donnons (est-ce le cas dans un cours en général?). De plus, le contenu doit également contenir un maximum d'informations afin de pouvoir être utile à d'autres personnes que les débutants ainsi que d'aider à la compréhension d'un maximum de codes.
Il est vrai que l'utilisation en qu'instruction de ? : n'est pas hyper fréquente car on lui préfère souvent || et && comme le disait Sylvain mais il est possible de la trouver quand même régulièrement dans le monde open source notamment.
En tout cas, bienvenue à toi, Damien, dans le groupe si tu souhaites participer. Nous allons lancer les exercices sur les tableaux et objets simples avec les boucles et autres (on ne parle par encore de prototype). Des exercices ont été fait (http://javascript.developpez.com/exe...age=Les-objets) mais il faudrait les mettre sous le même format que celui que tu as corrigé, retravailler la partie cours et corriger/améliorer ce qui ne te semble pas explicite donc si tu te sens d'attaque n'hésite pas! Ensuite nous passerons sur les fonctions et les scopes ce qui devrait être assez intéressant notamment avec tous les ajouts de l'ES6 sur le sujet!
Bonjour,
Merci de votre accueil. J'ai les accès accordés par vermine pour la correction orthographique.
Juste un mot sur la différence entre expression et instruction. Une expression représente une valeur, ce peut être une constante (3, "Bonjour"), une variable (x, y...) ou une construction syntaxique associant des constantes et/ou des variables et des opérateurs (3 + x, (x==0)?2:y...). On peut toujours utiliser une expression pour créer une autre expression. Sémantiquement une expression dénote une valeur.
Une instruction est une action qui, lors de son exécution, modifie l'état du système : x = 0; printf("Bonjour");. Une expression ne modifie pas l'état du système.
On retrouve cette dichotomie instruction/expression dans la dichotomie fonction/procédure. Une fonction dénote une expression, donc une valeur (son résultat) et ne doit pas modifier l'état du système. Le langage Ada par exemple, interdit ces modifications (on ne peut pas utiliser un paramètre donnée/résultat ou résultat, on ne peut pas modifier une variable globale).
C'est important pour les débutants (les débutants complets, ceux qui commencent la programmation) de bien comprendre cette dichotomie. La situation est bien différente évidemment dans notre cas, puisque ce sont des débutants en Javascript, mais pas des débutants en programmation.
Je vais tâcher de contribuer un peu et sans trop chipoter :-)
Cordialement,
Damien.
D'un point de vue théorique, ta remarque est intéressante. Peut-être peux-tu intégrer cette distinction dans un chapitre de cours de l'exercice pour voir ce que ça donne. Ensuite on publiera l'exercice.
Ensuite, je propose de passer à l'exercice http://javascript.developpez.com/exe...es-de-type-for! Il faut peaufiner le cours et mettre l'exercice dans le même format que le précédent.
Si! Cela peut être des débutants complets!Citation:
La situation est bien différente évidemment dans notre cas, puisque ce sont des débutants en Javascript, mais pas des débutants en programmation.
Pas de problème avec le chipotage, ça ne nous dérange pas, on fait la même chose bien souvent! ;)Citation:
Je vais tâcher de contribuer un peu et sans trop chipoter :-)
La proposition est déjà là ;). Je trouve cette proposition bien plus accessible et utile pour les débutants que la proposition actuelle qui peut prêter à confusion sauf peut-être pour les experts. Et en même temps je vois pas ce que les experts y perdraient. Peut-être je suis plus sensible aux arguments de genthial parce que je suis autodidacte, que mon premier langage a été Php et que j'ai toujours entendu parler d'expressions ternaires, jamais d'instructions.
Ce sont des définitions théoriques, mais est-ce qu'elles s'appliquent vraiment à JavaScript ? Ce qui se rapproche le plus de cette définition en JS à ma connaissance, ce sont les fonctions dites pures qui ont comme contrainte de ne rien modifier en dehors de leur scope (ce qu'on peut appeler l'état du système).
Pour être bien sûr de comprendre, j'ai par exemple cette ternaire sortie d'un de mes projets:
Instruction ou expression ? Le constructeur Model peut ou pas modifier l'état du système, on en sait rien. Mais dans tous les cas, c'est lisible donc un cas légitime d'utilisation, non ? :?Code:let model = o instanceof Model ? o : new Model(o);
C'est lisible mais pas explicite puisqu'à la lecture on ne sait justement pas trop les conséquences. Alors que si l'on réserve par convention les opérateurs ternaires à des expressions pour définir des variables on sait que cette ligne n'aura pas de conséquences autres que la définition/initialisation de la variable. Après c'est sûr qu'en pratique les frontières peuvent être poreuses.
Etant ignorant de la théorie et de l'origine des mondes, j'ai pensé que les opérateurs ternaires avaient été créés spécifiquement par le tout puissant pour nous faciliter la définition d'une variable sur une ligne plutôt que de nous obliger à un laborieux if/else. Et je les utilise abondamment tous les jours en remerciant le créateur :lol:
Si j'utilisais cet opérateur comme des instructions j'aurais l'impression de faire un détournement des fonctionnalités initiales, ce qui n'est pas grave au niveau du résultat, mais juste déroutant et perturbant, ne facilitant pas une lecture fluide et l'organisation du code, genre tout peut partir dans tous les sens à tout instant.
Voilà ce que j'ai cru comprendre par la pratique, et pour un débutant si on leur présente l'opérateur ternaire comme un équivalent d'instructions if/else, ça va pas faciliter leur progression car ils vont se poser moultes questions à savoir quand vaut-il mieux utiliser l'un que l'autre. Leurs idées et leur code risquent de partir dans tous les sens. Est-ce le bon moment pour tant de questions si l'on considère qu'on est dans les premiers exercices du tuto ? En voulant être exhaustif et sans commencer par l'utilisation la plus courante, c'est un peu comme si l'on présentait un cours de master à des sixièmes...
Personnellement, dans l'exemple de Sylvain j'aurais utilisé l'opérateur ternaire exactement comme lui car je trouve que c'est la notation la plus explicite.
L'utilisation de cet opérateur permet de signifier "dans un cas je fais ça, dans l'autre je fais ça" alors qu'avec l'utilisation d'un if...else, tu dois lire pour comprendre que c'est cette structure qui est utilisée, sans compter que celle-ci est facilement altérable.
Toi Damien, tu préfères ne l'utiliser qu'en mode "dans un cas je retourne cette valeur, dans l'autre celle-ci". Je comprends ton opinion même si je pense que la distinction est très peu faite particulièrement dans le milieu JavaScript (qui est friand de raccourcis syntaxiques).
Cependant, je trouve ton explication sur les instructions et expressions intéressante et je ne serai pas contre l'intégrer à l'exercice en l'illustrant avec l'opérateur ternaire. Les concepts de programmation, même s'ils ont peu de chance d'être compris à 100%, notamment par les apprenants débutants, sont une bonne plus-value. Comme on a décidé de les intégrer au fur et à mesure des exercices, ça ne serait pas incohérent d'en parler là.
Si ça te convient (et que ça convient à tout le monde), je te propose que tu rajoutes un petit paragraphe dans la partie cours sur le sujet qu'on voit ce que ça donne.
Cet exemple ne me pose pas de problème : l'opérateur est bien utilisé comme expression, la valeur de l'expression est un objet de type Model qui est affecté à une variable. Donc l'instruction c'est l'affectation à la variable.
Mais il est vrai que dans ce cas l'expression peut modifier l'état du système puisqu'elle crée un nouvel objet (et qu'en plus effectivement le constructeur peut lui même modifier l'état du système). Mais il y a deux niveaux : le niveau syntaxique (utilisation d'un opérateur comme instruction) et le niveau sémantique (modification ou non de l'état du système dans l'expression).
C'est surtout le niveau syntaxique qui peut créer des confusions dans l'esprit des débutants. Ils ont par exemple beaucoup de mal à se convaincre de l'équivalence de ces deux bouts de code :
et :Code:
1
2
3 while ((x = truc()) != 0) { ...traiter(x); }
C'est un cas typique de mélange instruction/expression : l'affectation est une instruction, puisqu'elle modifie une variable, mais elle est utilisée aussi dans le premier cas comme instruction.Code:
1
2
3
4
5 x = truc(); while (x != 0) { ...traiter(x); x = truc(); }
Pour un débutant, il ne fait aucun doute que la deuxième version est plus lisible et plus compréhensible, mais beaucoup de développeurs expérimentés utilisent la première (j'en suis).
Une erreur très fréquente des débutants est par exemple d'utiliser une fonction comme une procédure. Ils écrivent une fonction max qui retourne le max de deux valeurs puis écrivent sans trembler :
Question annexe : pour contribuer, on modifie directement les articles en ligne ou on poste une proposition de modification ici ?Code:
1
2 x = ...; max(x, 12);
Cordialement,
Damien.
C'est donc simplement l'aspect syntaxique qui peut perturber les débutants, l'aspect sémantique est aussi important, mais c'est un débat qui va nous entraîner trop loin (partisans du tout fonctionnel contre partisans de l'impératif).
Pour