Go: proposition : Go 2 : ajouter un opérateur conditionnel ternaire

Créé le 18 juil. 2019  ·  78Commentaires  ·  Source: golang/go

Je ne suis pas d'accord avec la convention Go et les arguments des concepteurs de langage ici https://golang.org/doc/faq#Does_Go_have_a_ternary_form et je pense que c'est une véritable fonctionnalité manquante dans le langage.

Considérons en C le code suivant :

printf("my friend%s", (nbFriends>1?"s":""));

ou en C++ :

std::cout << "my friend" << (nbFriends>1?"s":"") << std::endl;

En Go, cela provoque soit d'énormes répétitions qui peuvent provoquer des erreurs, soit un code très verbeux et inefficace, soit les deux, pour quelque chose qui devrait être simple :

Solution 1 :

// horribly repetitive, risk of divergence between the two strings
if nbFriends > 1 { 
  fmt.Printf("my friends\n") 
} else { 
  fmt.Printf("my friend\n")
}

Solution 2 :

// difficult to read
fmt.Printf("my friend")
if nbFriends > 1 { fmt.Printf("s") }
fmt.Printf("\n")

Solution 3 :

// difficult to read
var plural = ""
if nbFriends > 1 { plural = "s" }
fmt.Printf("my friend%s\n", plural)

Solution 4 :

// dangerous (ifTrue and ifFalse are both evaluated, 
// contrary to a real ternary operator), 
// and not generic at all (works only for strings)
func ifStr(condition bool, ifTrue string, ifFalse string) string {
  if condition { 
    return ifTrue
  }
  return ifFalse
}
fmt.Printf("my friend%s\n", ifStr(nbFriends > 1, "s", ""))

Solution 5 :

// horrible to read, probably inefficient
fmt.Printf("my friend%s\n",
        func(condition bool) string {
            if condition {
                return "s"
            }
            return ""
        }(nbFriends > 1))
Go2 LanguageChange Proposal Proposal-FinalCommentPeriod

Commentaire le plus utile

Je pense que l'exemple est un peu mauvais compte tenu de son seul caractère et n'est pas vraiment lisible à mon avis (?:"s":"")
mais je suis d'accord que l'opérateur ternaire devrait être ajouté, c'est une évidence pour moi
et j'ai inventé quelques exemples qui me seraient utiles personnellement et je pense que vous pouvez vous identifier à certains d'entre eux.

const PORT = production ? 80 : 8080
au lieu de

const PORT = -1
if production {
    PORT = 80
else {
    PORT = 8080
}

fmt.Printf("Running %s build!", production ? "Production" : "Debug") .. etc

Mais bien sûr, l'opérateur ternaire est très difficile à apprendre.

Tous les 78 commentaires

@gopherbot , ajoutez l'étiquette Go2, LanguageChange

Voir aussi #31659 et #32860.

Cette décision a déjà été consignée dans une FAQ, comme vous le notez. Si vous voulez faire valoir que la réponse de la FAQ devrait être modifiée, vous avez besoin de plus que quelques exemples. Je vous promets que nous avons déjà vu et examiné ces exemples. Ce dont vous avez besoin, ce sont des données : de vrais programmes avec un code qui deviendrait plus simple et plus facile à lire en ajoutant un opérateur conditionnel. Vous avez également besoin d'arguments contre les préoccupations courantes concernant l'opérateur conditionnel, telles que le fait qu'il rend le code plus difficile à lire, en particulier lorsqu'il est imbriqué.

Aussi, un point mineur, mais votre exemple n'est pas génial car il ne fonctionne que pour l'anglais et ne prend pas en charge la localisation des chaînes de message.

@ianlancetaylor

Dans #31659, vous avez fait ce que je pensais être une très bonne contre-suggestion d'avoir une fonction intégrée cond pour fournir une fonctionnalité ternaire. Cela devait être une fonction intégrée (par opposition à une fonction générique) pour permettre une évaluation en court-circuit des arguments vrai/faux. Il souffrait toujours de la possibilité que les gens puissent imbriquer des fonctions cond bien que personnellement je ne considère pas cela comme un problème fatal car, même s'ils le faisaient, il devrait toujours être plus lisible que les hiéroglyphes de l'opérateur ternaire de C lui-même .

Cette proposition étant maintenant close, avez-vous l'intention de poursuivre cette suggestion ou avez-vous complètement abandonné l'idée d'avoir une forme ternaire alternative ?

Personnellement, je n'ai pas l'intention de pousser cette idée plus loin. C'était plus une discussion qu'une suggestion sérieuse. Bien sûr, cela ne me dérange pas si quelqu'un veut en faire une vraie proposition. Mais pour être accepté, je pense que nous aurions encore besoin de voir dans quelle mesure cela simplifierait les vrais programmes existants.

D'accord, merci d'avoir précisé.

Il suffit de regarder le code dans d'autres langages de la famille C pour voir à quel point l'opérateur ternaire est courant, mais il serait difficile d'analyser le code Go lui-même car, comme @Phrounz l' a souligné dans son article d'ouverture, un certain nombre de constructions sont utilisées pour fonctionner autour de son absence.

En utilisant l'idée cond , son exemple deviendrait :

fmt.Printf("my friend%s\n", cond(nbFriends > 1, "s", ""))

Cela dit, si nous obtenons des génériques, je me contenterais personnellement d'écrire ma propre fonction cond et, étant donné l'absence de court-circuit, je ne l'utiliserais que là où les arguments étaient peu coûteux à évaluer.

À mon avis, écrire plus de code (juste quelques lignes) vaut mieux que de comprendre la règle de x ? a : b . L'instruction if peut sembler verbeuse (pas sûr) mais facile à comprendre.

De plus, un opérateur conditionnel ternaire peut être facilement abusé lorsque les gens écrivent plusieurs x ? a : b imbriqués. L'avantage de l'introduire n'est pas assez grand.

Je vois que les opérateurs ternaires ne sont faciles à visualiser que dans les fonctions à une ligne. Même dans ce cas, la plupart du temps, ils traitent de la gestion des erreurs, auquel cas il est préférable d'adhérer à une approche "moins d'indentation, mieux c'est" en faisant en sorte que l'erreur ou le chemin le moins probable pour une fonction soit enveloppé dans un if et traité ensuite, au lieu d'avoir une logique de branchement multiple.

Je pense que l'exemple est un peu mauvais compte tenu de son seul caractère et n'est pas vraiment lisible à mon avis (?:"s":"")
mais je suis d'accord que l'opérateur ternaire devrait être ajouté, c'est une évidence pour moi
et j'ai inventé quelques exemples qui me seraient utiles personnellement et je pense que vous pouvez vous identifier à certains d'entre eux.

const PORT = production ? 80 : 8080
au lieu de

const PORT = -1
if production {
    PORT = 80
else {
    PORT = 8080
}

fmt.Printf("Running %s build!", production ? "Production" : "Debug") .. etc

Mais bien sûr, l'opérateur ternaire est très difficile à apprendre.

Oui, c'est un bon exemple, surtout si c'est au niveau supérieur :

const production = true

//...

const PORT = production ? 80 : 8080

car vous n'avez alors pas besoin d'une fonction init pour initialiser PORT.

Une fonction cond intégrée _pourrait_ pouvoir être utilisée comme initialiseur const bien qu'une version générique ne le puisse certainement pas.

@Terottaja @alanfo

Je pense que la solution idiomatique à ce problème spécifique est d'utiliser Build Constraints .

@Terottaja

Voir mon autre commentaire pour la solution pour les variables/constantes globales.

Pour les variables/constantes locales, je pense que la façon idiomatique d'écrire cette paix de code :

const PORT = -1
if production {
    PORT = 80
else {
    PORT = 8080
}

est:

PORT := 8080
if production {
    PORT = 80
}

Vous pourriez dire que j'ai changé le const en var , mais je serais surpris si le compilateur n'était pas assez intelligent ™ pour comprendre que PORT est constant, donc IMO cela ne fait aucune différence dans le code réel.

Bien que cela n'aurait probablement pas d'importance dans cet exemple particulier que PORT soit un const ou un var , plus généralement, cela pourrait avoir de l'importance. Par exemple, si vous déclariez un entier qui devait être utilisé pour définir la taille d'un tableau.

Peut-être devrais-je préciser ma propre position sur cette proposition. Bien que je n'aie personnellement aucun problème avec l'opérateur ternaire "standard", je ne suis pas sûr que ce soit une bonne idée de l'introduire dans Go sous cette forme. Je préférerais de loin un cond intégré à la place qui est beaucoup plus lisible bien que, de manière réaliste, je vois peu de chances d'être adopté.

@Terottaja

Voir mon autre commentaire pour la solution pour les variables/constantes globales.

Pour les variables/constantes locales, je pense que la façon idiomatique d'écrire cette paix de code :

const PORT = -1
if production {
  PORT = 80
else {
  PORT = 8080
}

est:

PORT := 8080
if production {
  PORT = 80
}

Vous pourriez dire que j'ai changé le _const_ en _var_, mais je serais surpris si le compilateur n'était pas _assez intelligent ™_ pour comprendre que _PORT_ est constant, donc IMO cela ne fait aucune différence dans le code réel.

je parle juste de si vous avez beaucoup de ce genre de choses dans votre code, l'opérateur ternaire serait certainement plus propre dans ce cas, juste mon avis

À mon avis, écrire plus de code (juste quelques lignes) vaut mieux que de comprendre la règle de x ? a : b . L'instruction if peut sembler verbeuse (pas sûr) mais facile à comprendre.

De plus, un opérateur conditionnel ternaire peut être facilement abusé lorsque les gens écrivent plusieurs x ? a : b imbriqués. L'avantage de l'introduire n'est pas assez grand.

il y aura toujours des gens qui en abuseront, le code peut être abusé, c'est inévitable, mais cela vous affectera-t-il ? dans la plupart des cas, non

Je supporte cette fonctionnalité, bien qu'elle puisse conduire à des abus dans le code, elle est vraiment bénéfique pour les optimisations du compilateur, lorsque vous évitez le générique if/else et que vous le remplacez par un opérateur ternaire.
Les gens ont fait des décalages au niveau du bit depuis le début (qui peut les blâmer, et personne ne suggère de supprimer les décalages au niveau du bit à cause de la lisibilité), et l'opérateur ternaire est tout simplement crucial d'avoir de nos jours.

@Lexkane : Le compilateur a déjà des optimisations qui utilisent des déplacements conditionnels. Nous n'avons pas besoin d'une construction de langage pour forcer de telles optimisations. Par exemple, le code suivant en utilise un :

func f(x, y int) int {
    r := 3
    if x < y {
        r = 7
    }
    return r
}

Si vous avez des cas particuliers où un mouvement conditionnel n'est pas généré, et que vous pensez qu'il le devrait, ouvrez un problème avec le code.

Depuis que j'utilise Go et Javascript dans mon travail en même temps, cela fait un nombre incalculable de fois que j'ai voulu écrire x ? a : b dans des programmes Go ! J'aurais dû l'écrire pour montrer tous ces cas à @ianlancetaylor ! C'était de vrais programmes.
L'opérateur ternaire est celui que nous apprenons tous à l'école (pas même à l'université), donc dans sa forme classique, c'est la manière naturelle d'écrire et de lire du code.
Nous avons tous appris qu'il existe trois types d'opérateurs : unaire, binaire et ternaire. Go manque un type sans raison réelle IMO.
Les deux mains x ? a : b .

Nous avons tous appris qu'il existe trois types d'opérateurs : unaire, binaire et ternaire. Go manque un type sans raison réelle IMO.

Il n'y a aucune raison pour qu'il y en ait, cependant. 'ternaire' est juste un mot anglais qui signifie 'composé de quatre parties'. Vous pourriez tout aussi bien avoir des opérateurs quaternaires ou quinaires.

Personnellement, je pense que les opérateurs ternaires sont par défaut ennuyeux à lire. Avec les opérateurs unaires et binaires, vous pouvez facilement voir exactement où tout se trouve, mais avec le ternaire, il n'est pas toujours clair ce qui va avec quoi, surtout une fois que vous commencez à les imbriquer. Je peux voir l'argument pour qu'ils soient plus propres dans des situations spécifiques, mais en dehors de ces situations, ils sont presque toujours pires. gofmt pourrait aider, potentiellement, mais seulement s'il était beaucoup plus agressif sur la façon dont il reformate le code qu'il ne l'est. Peut-être qu'une sorte de limitation pourrait être introduite, comme interdire l'imbrication ou l'enchaînement, mais à ce stade, je ne sais pas si cela en vaut vraiment la peine.

Il a déjà été dit que l'on peut semer la pagaille avec l'ensemble d'opérateurs le plus simple. Il est vrai que le code Go est plus simple à lire et à écrire que le code Java ou Javascript. Mais il n'est pas impossible de le rendre illisible.
L'opérateur ternaire est donc principalement destiné aux lignes simples et doit être utilisé dans ces cas.
Sinon, vous pouvez prendre "if - then - else", l'imbriquer plusieurs fois et faire de votre code un gâchis total. C'est toujours à vous de décider.
Je pense que les gens sous-estiment la fréquence des expressions à une ligne qui apparaissent dans le code. Parfois, ils sont rares, mais parfois ils remplissent la moitié du code écrit et, dans le cas ultérieur, je souhaite avoir un opérateur ternaire de préférence sous sa forme en Javascript.

J'aime le fait que dans Go, le flux de contrôle se fasse généralement avec des instructions, pas des expressions (l'invocation de fonction étant l'exception évidente). De nombreux langages populaires s'efforcent de "tout est une expression", ce qui est souvent amusant, mais imo encourage l'écriture de code "intelligent". Go, pour moi, consiste à minimiser l'intelligence.

Soit dit en passant, une autre façon (grossière) d'implémenter une expression ternaire est :

map[bool]string{true: "", false: "s"}[nbFriends == 1]
map[bool]string{true: "", false: "s"}[nbFriends == 1]

belle astuce mais bien plus "astucieuse" que la simple annonce bien connue évidente ? : .

Certaines fonctionnalités classiques pourraient être néfastes mais nous nous y sommes déjà habitués. On ne s'en rend même pas compte.

La condition doit être un booléen, donc parfois nous devons écrire

x := 0
y := x != 0 ? 1 : 2

Ce n'est pas intuitif. Parce que dans l'instruction if vous voyez if à première vue et vous savez qu'il y aura une condition.

Dans une expression ternaire, ce n'est que si vous voyez ? que vous saurez qu'il s'agit d'une condition. Vous serez surpris et reviendrez relire la condition quand c'est compliqué.

Il rompt le flux de lecture de gauche à droite, de haut en bas.

Vous pourriez dire que j'ai changé le _const_ en _var_, mais je serais surpris si le compilateur n'était pas _assez intelligent ™_ pour comprendre que _PORT_ est constant, donc IMO cela ne fait aucune différence dans le code réel.

Eh bien, cela fait une différence en perdant la constance. Const n'est pas seulement une question d'optimisation. Le code plus bas peut maintenant jouer avec la valeur

Que diriez-vous de : autoriser le ternaire mais interdire de les imbriquer.
J'aimerais ça.

La seule raison pour laquelle something ? foo : bar _semble_ lisible est que nous sommes déjà habitués à l'utiliser dans d'autres langues. Mais cela n'est en aucun cas plus lisible ou plus clair que

if something {
  foo
} else {
  bar
}

spécialement pour les nouveaux arrivants dont Go est la langue maternelle.

Si la lisibilité n'est pas meilleure, le seul gain possible est d'écrire moins de lignes de code. Pour moi, cela ne semble pas être une raison suffisante pour introduire une construction alternative pas très intuitive pour quelque chose que nous avons déjà.
Nous avons déjà if . Pourquoi ajouter une autre façon moins intuitive de faire la même chose ?

if something {
  foo
} else {
  bar
}

'else' rompt également la ligne de mire et la lisibilité (vous devez revenir en arrière et lire à nouveau si la condition). Je ferais mieux de me débarrasser de 'else' au profit de '?'.

La seule raison pour laquelle something ? foo : bar _semble_ lisible est que nous sommes déjà habitués à l'utiliser dans d'autres langues. Mais cela n'est en aucun cas plus lisible ou plus clair que

if something {
  foo
} else {
  bar
}

Eh bien, c'est plus clair à plusieurs égards:

  • il réduit la cérémonie pour ce qui est essentiellement une opération triviale,
  • il exprime une affectation sur une ligne,
  • cela nous permet de garder la variable comme "const" (et donc de réduire la charge mentale et la possibilité de jouer avec plus tard),
  • c'est 5 lignes de moins et il est donc plus facile de prendre plus de code.

spécialement pour les nouveaux arrivants dont Go est la langue maternelle.

Pourquoi une langue concentrerait-elle son expressibilité sur les nouveaux venus ? C'est comme créer une interface utilisateur simpliste uniquement pour les analphabètes informatiques, et donc frustrer quiconque dépasse un certain point et manque la puissance supplémentaire.

@bugpowder L' expression ternaire est totalement remplaçable et l'instruction if est plus intuitive, plus expressive et plus courante.

@bugpowder L' expression ternaire est totalement remplaçable et l'instruction if est plus intuitive, plus expressive et plus courante.

Qu'en est-il des cas similaires;

println("Example bool is: ", bool ? "true" : "false")
c'est vraiment là où ça brille pour moi où vous ne pouvez vraiment pas utiliser l'instruction if à moins que vous ne vouliez que votre code ressemble à ceci :

bool := "false" if bool { bool = "true" } println("Example bool is: ", bool ? "true" : "false")

La seule raison pour laquelle something ? foo : bar _semble_ lisible est que nous sommes déjà habitués à l'utiliser dans d'autres langues. Mais cela n'est en aucun cas plus lisible ou plus clair que

if something {
  foo
} else {
  bar
}

spécialement pour les nouveaux arrivants dont Go est la langue maternelle.

Si la lisibilité n'est pas meilleure, le seul gain possible est d'écrire moins de lignes de code. Pour moi, cela ne semble pas être une raison suffisante pour introduire une construction alternative pas très intuitive pour quelque chose que nous avons déjà.
Nous avons déjà if . Pourquoi ajouter une autre façon moins intuitive de faire la même chose ?

À l'époque où j'ai appris à coder, l'opérateur ternaire semblait un peu étrange et complexe au début, mais après l'avoir recherché plus en détail et vu ces exemples tels que :

true ? "it's true!" : "It's false!"
cela semblait vraiment logique et simple, mais ce n'est que moi. peut-être que pour d'autres c'est plus complexe et difficile à comprendre.

Je ne suis pas d'accord avec la convention Go et les arguments des concepteurs de langage ici https://golang.org/doc/faq#Does_Go_have_a_ternary_form et je pense que c'est une véritable fonctionnalité manquante dans le langage.

Mais la dernière phrase d'une FAQ explique clairement « pourquoi il n'y a pas ? : » :

Un langage n'a besoin que d'une seule construction de flux de contrôle conditionnel.

La possibilité de presser plus de logique dans une ligne ne donne rien de nouveau du tout. Il existe déjà un moyen propre de modifier le flux de contrôle, un autre est tout simplement excessif.

Regardons ce qui ne va pas avec l'expression ternaire. Dans un cas simple, les deux sont ok.

var a, b int
fmt.Println("Example bool is: ", a != 0 && b != 0 ? "true" : "false")
var a, b int
var c string
if a != 0 && b != 0 {
        c = "true"
} else {
        c = "false"
}
fmt.Println("Example bool is: ", c)

Lorsque les choses deviennent complexes (ajoutez une condition), l'expression ternaire semble ambiguë.

Cependant, le formulaire if-else fait son travail. Je pense qu'une forme plus courte n'est pas toujours la forme la plus claire.

var a, b, c int
fmt.Println("Example bool is: ", a != 0 && b != 0 ? c != 0 ? "true" : "false" : "false")
var a, b, c int
var d string
if a != 0 && b != 0 {
        if c != 0 {
                d = "true"
        } else {
                d = "false"
        }
} else {
        d = "false"
}
fmt.Println("Example bool is: ", d)

L'expression ternaire n'est qu'un cas particulier de l'instruction if. Cela ne vaut pas la peine d'ajouter une nouvelle syntaxe pour un simple cas particulier.

Oui, s'il te plait, oui ! J'adore Go et il met l'accent sur la lisibilité, mais cela a un prix en tant que code très verbeux.
Je crois fermement que l'opérateur ternaire améliorera "l'inscriptibilité" sans nuire à la lisibilité. Cela rendra simplement le code de Go un peu plus élégant et pratique.

En parlant d'ambiguïté et d'autres problèmes de codage, je dirais que les développeurs ayant de mauvaises pratiques de codage écriront de toute façon du mauvais code sans opérateur ternaire.

@ziflex IMHO, la meilleure pratique de codage pour éviter l'ambiguïté est de NE PAS utiliser d'expression ternaire même dans une langue avec une expression ternaire.

Il y a des pièges à éviter donc il faut apprendre des pratiques de codage comme

  1. ne l'imbriquez pas.
  2. ne l'utilisez que dans un cas très simple.
  3. lorsque la logique devient complexe, réécrivez-la sous la forme if-else.
    ...

Ces pièges vous amèneront au-dessus.

@DongchengWang Certaines de ces pratiques peuvent être facilement applicables aux déclarations «si» simples.

Beaucoup de répondants disent que le ternaire est remplaçable et n'apporte rien de nouveau.

Mais en même temps, je vois combien de personnes utilisent "if err := MaybeError(); err != nil {}" qui peut également être facilement réécrit avec des instructions "if" simples. Mais pour une raison quelconque, personne ne s'en plaint vraiment. Pourquoi? Parce que c'est pratique. Et probablement parce que c'était dans la langue depuis le début.

La seule raison pour laquelle nous nous disputons à ce sujet, c'est simplement parce que l'opérateur n'était pas là depuis le début.

Personnellement, il y a eu quelques occasions où avoir une expression ternaire aurait donné un code plus propre et moins imbriqué. Seulement quelques-uns cependant, donc je ne suis pas marié à ça...

Pour éviter la complexité supplémentaire de la syntaxe en utilisant les caractères plus ou moins standard ?: , qu'en est-il de la réutilisation des mots-clés de langage existants comme dans le cas de la boucle for comme suit ?

port := 80 if production else 8080

Cela vous permet toujours d'enchaîner et d'en abuser, mais seulement autant que vous le pouvez avec un bloc traditionnel if/else ...

Je pense que vous devriez encore méditer sur les principes de la naissance de ce langage : une façon simple et évidente de faire les choses, des fonctionnalités orthogonales et des bibliothèques.

Je pense que nous sommes à quelque chose comme 70% là-bas. Tout n'est pas parfait.

Ce que j'aime à propos de Go jusqu'à présent, c'est le fait qu'il atténue les disputes entre les membres de l'équipe sur la manière de coder, sur le style de code que chacun peut utiliser (vous vous souvenez des différentes versions de PSR en PHP ?). Nous, dans notre équipe de 7 membres, ne nous disputons jamais sur les codes de l'autre. Nous nous concentrons uniquement sur notre objectif.

Non pas que je n'aime pas l'opérateur conditionnel ternaire, mais je dois m'opposer à l'ajouter et quoi que ce soit de ce genre à Go parce que je n'aime pas que la façon de coder devienne l'un de nos arguments.

Sucre inutile. Je pense que c'est un de ces moments où nous essayons d'apporter quelque chose qui "a été utilisé dans une autre langue". Ne se sent pas Go.

Comme indiqué ci-dessus, il existe une entrée de FAQ expliquant pourquoi le langage n'a pas l'opérateur conditionnel. La question n'a pas de soutien solide. L'ajout d'une nouvelle fonctionnalité au langage ne peut jamais le rendre plus simple. Une fois qu'il y a deux façons de faire quelque chose ( if ou ?: ), chaque programmeur devra souvent décider quelle forme utiliser, ce qui n'est pas une bonne chose. En général, nous ne voyons pas de nouveaux arguments ici.

Il s'agit donc d'un déclin probable . Laissant ouvert pendant un mois pour les commentaires finaux.

Au point de @ziflex , je ne sais pas comment une ligne détaillée si:

if bool := operation(); bool {}

est très différent d'un opérateur ternaire. C'est une construction que je n'abandonnerais pas volontiers, mais elle a la possibilité de souffrir de la même complexité qu'un eval ? a : b comme :

func main() {
    if a := A(); !B(a) && !C(a) && D(C(a)) {
        fmt.Println("confused")
    }
}

func A() bool {
    return true
}

func B(in bool) bool {
    return !in
}

func C(in bool) bool {
    return in
}

func D(in bool) bool {
    return in
}

Cela ne sert qu'à illustrer qu'un code mal écrit sur une seule ligne peut devenir aussi illisible que certains des exemples ci-dessus. La possibilité d'abuser d'une syntaxe, à mon humble avis, ne devrait pas être une raison suffisante pour empêcher l'ajout d'un opérateur utilisable de manière significative au langage.

Cependant, le formulaire if-else fait son travail. Je pense qu'une forme plus courte n'est pas toujours la forme la plus claire.

var a, b, c int
fmt.Println("Example bool is: ", a != 0 && b != 0 ? c != 0 ? "true" : "false" : "false")

C'est un mauvais exemple, car vous avez omis les parenthèses, ce qui rend votre exemple extrêmement obscur alors qu'il pourrait être compréhensible.

je pense sincèrement
go var a, b, c int fmt.Println("Example bool is: ", (a != 0 && b != 0 ? (c != 0 ? "true" : "false") : "false"))

est plus lisible que

var a, b, c int
var d string
if a != 0 && b != 0 {
        if c != 0 {
                d = "true"
        } else {
                d = "false"
        }
} else {
        d = "false"
}
fmt.Println("Example bool is: ", d)

(Même si votre exemple pourrait en fait être encore plus simple, mais je suppose que ce n'est pas le but : )

go fmt.Println("Example bool is: ", (a != 0 && b != 0 && c != 0 ? "true" : "false"))

Bien que je me retrouve parfois à vouloir un conditionnel dans d'autres expressions ou déclarations, j'ai presque toujours l'impression que ce serait une perte nette de lisibilité.

La seule chose que je regrette à ce sujet est l'absence d'un moyen d'avoir une initialisation conditionnelle où les deux branches ne seraient pas une valeur nulle. Je sais que le compilateur est probablement assez intelligent pour que cela ne soit pas un gaspillage, mais mon sens de ce que fait la machine abstraite me dit que je mets à zéro une valeur, puis que je l'écrase immédiatement. C'est... un argument assez faible, vraiment.

FWIW, je ne trouve pas la forme ternaire des exemples "Example bool" plus lisible, notamment parce que, sur mon écran en ce moment, ils finissent par nécessiter un défilement horizontal pour même voir l'expression complète. Même en faisant cela, je dois regarder en arrière beaucoup plus souvent pour comprendre ce qu'il fait.

La réponse évidente de certains langages de script est d'avoir des instructions if comme des expressions qui peuvent être assignées, et j'aime vraiment beaucoup cette conception pour ces langages, mais je ne pense pas que je l'aimerais tellement pour aller.

Je suppose qu'il y a toujours :

x := func() int {
    if a {
        return 1
    }
    return 2
}()

... mais à bien y penser, si nous pouvions rationaliser cela, ce serait en fait assez utilisable dans des circonstances comme celle-ci. Quelque chose qui nous permet d'exprimer "cette fonction est en fait simplement notationnelle, il n'est pas nécessaire de générer réellement du code de fonction, nous voulons juste un moyen d'utiliser des expressions de retour dans un bloc interne"...

Le langage Go est né pour la simplicité. Pourquoi voulez-vous faire ces choses fantaisistes ? Vous avez l'impression d'avoir écrit quelques lignes de code, mais cela ajoute plus de complexité et de confusion au code.
donc je ne supporte pas

Ce n'est pas "fantaisiste", c'est "simple" donc ça s'intègre parfaitement. C'est familier parce que nous l'utilisons dans de nombreuses autres langues. C'est pratique car il s'agit d'une expression sur une seule ligne avec peu de saisie. C'est important parce que c'est une construction commune que nous utiliserions beaucoup.

Ensuite, je préférerais utiliser une compréhension de liste comme python :
a if a>1 else b
Au lieu de toutes sortes de symboles étranges, tout comme Rust.
Je préfère écrire plus de code pour l'exprimer que d'utiliser ces étranges symboles pour omettre le code.
Le code est à lire par les gens.

Veuillez ne pas ajouter de nouvelles fonctions de grammaire pour une situation qui n'est pas couramment utilisée, car vous détruisez l'intention originale de Go, c'est-à-dire simple et facile à lire.
Je pense que parfois, beaucoup de gens sont égoïstes, pour leur commodité dans certaines situations, ou parce qu'ils sont gâtés par les fonctionnalités de commodité fournies par d'autres langages de programmation, il faut ajouter leurs fonctionnalités préférées dans Go.
Ce que je veux dire, c'est que Go n'est pas votre langue, Go a sa propre voie à suivre.
Bien que vous puissiez inventer votre propre langage, vous le pouvez.

@Yanwenjiepy On dirait que vous êtes également devenu un "puriste" de Go qui, à mon avis, entrave le progrès.

I would rather write more code to express it than to use these strange symbols
Cela peut vous sembler étrange, mais pas des symboles étranges pour la plupart d'entre nous qui connaissent n'importe quel langage courant basé sur C; C, C++, C#, Java, JavaScript, etc. Ils ont tous l'expression ternaire.

Please don't add new grammar functions for a situation that is not commonly used
Les instructions conditionnelles ternaires sont en fait très pratiques et couramment utilisées !

Juste pour être pointilleux, ce n'est pas une "compréhension de liste". Une compréhension de liste est spécifiquement quelque chose comme [x for y in z] (éventuellement plus des conditions). L'utilisation de if/else dans les expressions est une fonctionnalité différente.

Je connais très bien les opérateurs ternaires et j'ai utilisé des langages qui en avaient pendant la majeure partie de ma vie, mais environ 95% des utilisations que j'ai vues dans d'autres langages, je pense que ce serait un mauvais choix pour ce qui rend Go agréable à travailler in. Go a eu tendance à éviter la densité d'informations de certains types, comme les opérateurs de pré-incrémentation/post-incrémentation qui peuvent être utilisés dans les expressions, et je pense que l'opérateur ternaire a le même problème sous-jacent ; il faut trop d'espace pour réfléchir à ce qu'il fait.

Le compilateur est raisonnablement intelligent. Vous pouvez déclarer une valeur, lui attribuer une condition, l'utiliser une fois et vous attendre à ce que le compilateur fasse à peu près aussi bien qu'il le ferait pour une expression ternaire.

@Yanwenjiepy On dirait que tu es devenu un "puriste" de Go aussi, ce qui à mon avis freine les progrès.

I would rather write more code to express it than to use these strange symbols
Pour la plupart d'entre nous qui connaissent n'importe quel langage C courant, cela peut être une notation étrange, mais pas étrange ; C, C++, C#, Java, JavaScript, etc. Ils ont tous deux des expressions ternaires.

Please don't add new grammar functions for a situation that is not commonly used
Les instructions conditionnelles ternaires sont en fait très pratiques et couramment utilisées !
Peut-être que j'ai moi-même un sentiment similaire. Peut-être que sur d'autres questions, je ne suis pas un " puriste du Go ". C'est très déroutant.

@seebs Je peux certainement respecter cette opinion, mais pour beaucoup d'entre nous venant d'autres langages basés sur C, "agréable à travailler" signifie productivité via la familiarité et la commodité. Je ne pourrais jamais comprendre pourquoi i++ en Go est moins agréable/pratique que i = i + 1 , surtout quand un post-incrément est correct dans les boucles, par exemple for i := 0; i < 5; i++ {...} mais ce n'est pas OK comme déclaration ! Trop de purisme je dis ! :)

Qu'est-ce que tu racontes? i++ est parfaitement acceptable comme instruction dans Go. ce qui n'est pas autorisé, c'est de l'utiliser dans une _expression_, où il est évalué à la fois pour une valeur et pour un effet secondaire.

https://play.golang.org/p/m_LbSbmT1Ar

En tant que personne raisonnablement familiarisée avec C, je trouve néanmoins que je vais bien sans l'opérateur ternaire, et j'aime mieux le code résultant. J'ai aussi cessé de l'utiliser autant en C, tout comme je suis devenu plus cohérent dans l'utilisation des accolades sur tous les blocs, pas seulement sur les blocs contenant plus d'une instruction.

Je ne voulais pas dire i++ en soi, je voulais dire comme une expression comme fmt.Printf("%d", i++) qui serait une commodité pour certains d'entre nous.

Oui, c'est certainement pratique, mais c'est, assez clairement, moins maintenable. Les gens font des erreurs avec, les gens comprennent mal le code qui l'utilise. C'est une source de bogues, et cela n'ajoute tout simplement pas beaucoup de valeur.

Oui, si je veux faire x++ , je dois le faire comme sa propre déclaration avant ou après le Printf . C'est en effet un coût, du tout. Mais en échange, j'obtiens :

  • Je n'ai pas soudainement x obtenant les mauvaises valeurs si je commente certains des appels Printf.
  • Les modifications apportées aux messages de format ne brisent pas la logique de mon programme.
  • Quelqu'un d'autre qui parcourt le code (ou moi sans assez de café) ne manquera pas simplement que l'incrément soit là.

C'est un compromis, mais je pense que c'est un très bon compromis. Je passe une partie de mon temps à essayer de répondre aux questions des débutants sur la programmation, car cela fait partie de la façon dont nous développons des communautés linguistiques plus saines. Je passe beaucoup moins de temps à essayer de démêler les subtilités de la ponctuation dans le code Go des gens que dans leur code C, et ils ont beaucoup moins de problèmes causés entièrement par des fautes de frappe subtiles.

Je vous assure que ce n'est pas du purisme venant de gens qui ne comprennent pas ou n'apprécient pas le C. C'est une décision réfléchie que ce langage semble tirer beaucoup de valeur du simple fait qu'il n'est pas si compliqué, et cela nous laisse plus de place pour être faire des choses compliquées avec notre logique puisque nous ne dépensons pas autant d'efforts pour analyser le code.

Je vous entends, mais je ne suis pas convaincu sur tout cela. Par exemple, ce qui suit fonctionne dans Go et selon votre argument, ce devrait être la seule syntaxe autorisée :

    for i:=0; i<5; i=i+1 {
      fmt.Printf("%d\n", i)
    }

Mais la syntaxe la plus populaire/familière EST également autorisée :

    for i:=0; i<5; i++ {
      fmt.Printf("%d\n", i)
    }

Pourquoi pensez-vous que c'est?

Mon argumentation ne dit pas en effet que seule la première devrait être autorisée. J'aime mieux le second, c'est plus simple et plus facile à lire, car l'opérateur d'incrémentation est une chose autonome, pas un effet secondaire .

Notez que vous ne pouvez pas faire :

i := 0
for i++ < 5 {
    ...
}

Parce que Go ne vous permet pas de mettre des affectations ou des incréments dans les expressions. Et cela peut parfois être un inconvénient, mais la fréquence avec laquelle les gens ne comprennent pas mal une expression et ne réalisent pas qu'elle modifie les valeurs est fondamentalement de 100 %, ce qui est bien.

Vous voyez, c'est trop puriste pour moi :) Quoi qu'il en soit, ce que je veux dire, c'est que puisque i=i+1 et i++ sont autorisés dans les boucles, je dis également d'autoriser une variation ternaire pour ceux qui préfèrent la commodité d'une seule ligne , par exemple

```Allez
Port := fabrication ? 80 : 8080

as well as the usual:

```Go
Port := 8080
if production {
    Port = 80
}

S'il s'agit de simplicité, je pense que le premier est plus simple.

Qu'en est-il de:

Port := production++

ou

fmt.Printf("port: %d\n", production++)

Les deux sont également plus courts en utilisant l'idiome C qu'ils ne le seraient en Go. Mais je dirais que dans les deux cas, la possibilité que cette complexité existe rend l' ensemble du programme légèrement plus difficile à comprendre - vous devez maintenant faire attention à ces effets tout le temps.

A un niveau philosophique plus fondamental : Le problème est que votre solution n'est pas seulement pour ceux qui préfèrent cette "commodité". Il est également imposé par la force à tous les autres, pour toujours. Parce que tout le monde doit lire le code des autres . Les gens ne peuvent donc pas désactiver une fonctionnalité comme celle-ci. Ils ne peuvent pas dire "eh bien, c'est plus difficile à maintenir pour moi, donc je ne l'utiliserai pas" et ne pas avoir à s'en occuper. Ils sont coincés avec cela faisant partie de leur monde. Chaque fois qu'ils lisent du code sur lequel n'importe qui d'autre aurait pu travailler, ils doivent faire attention à un nouvel ensemble de complexités.

En pratique, cette "simplicité" a un coût important, car ce n'est pas vraiment de la simplicité , c'est juste rendre l'expression plus courte. C'est comme la simple ligne sans accolade if ; il semble que ce soit plus simple, mais alors vous avez besoin d'une deuxième ligne et il y a une chance non nulle que vous oubliez d'ajouter les accolades alors, et bientôt vous avez perdu plus de temps que vous n'auriez simplement mis les accolades là.

Je sais ce qui se passe si vous écrivez :

Port := production ? 80 : 8080

Quelques jours plus tard:

Port := production ? 80 : test ? 4080 : 8080

Mais ensuite, quelqu'un se rend compte que les deux bools sont un mauvais choix et corrige cela :

Port := mode == "production" ? 80 : mode == "test" ? 4080 : 8080

et parce que ce n'était qu'une ligne, et en utilisant ?: , les gens ont l'impression que l'allonger est un effort supplémentaire, et ils ne le réparent pas ou ne le nettoient pas. Et maintenant, ils ont un investissement pour que ce soit ainsi.

Et c'est ainsi que vous vous retrouvez avec des opérations ?: imbriquées à 15 profondeurs, ce que j'ai vu dans le code réel, qui aurait dû absolument être des tables de recherche.

Et c'est comme ça que vous vous retrouvez avec ?: opérations imbriquées à 15 profondeurs, que j'ai vues dans le code réel, qui auraient dû absolument être des tables de recherche.

Cependant, les opérations "if-else" imbriquées à 15 profondeurs auraient également dû être des tables de recherche.

Ah, certainement.

Mais si vous avez 15 opérations if/else imbriquées en profondeur et que vous convertissez en une table de recherche, vous n'avez pas l'impression d'avoir perdu la "simplicité" de la solution à une seule ligne.

Le problème est que votre solution n'est pas seulement pour ceux qui préfèrent cette "commodité". C'est aussi imposé par la force à tout le monde, pour toujours

Je ne pourrais pas être plus en désaccord car la vérité est le contraire! C'est en fait votre vision puriste qui impose votre façon de faire et limite ma liberté de choisir une version abrégée . Si vous ne voulez pas l'utiliser, c'est votre choix, mais ne limitez pas mon choix !

Si je peux choisir d'écrire un raccourci a := "freedom" au lieu de var a string = "freedom" alors je devrais avoir la liberté et la commodité d'une affectation ternaire.

Go tooling fait un excellent travail de standardisation du formatage du code et je pense que cela seul facilite la lecture du code des autres.

L'essentiel pour moi est que je trouve les devoirs ternaires plus faciles à lire et à comprendre car ils sont plus naturellement traduits en anglais. Je crois que c'est pourquoi il est si populaire dans de nombreuses autres langues. Pour moi ça :

port := production ? 80 : 8080

... se traduit par : "Est-ce que c'est de la production ? Si oui, le port est 80 et si non, le port est 8080"
(une affectation unique simple et directe, même lorsqu'elle est imbriquée)

port := 8080
if production {
    port = 80
}

Cela se traduit par : "le port est 8080 (point) Oh, mais s'il s'agit de production, changez le port en 80" (deuxième affectation).

Le second n'est certainement PAS plus facile à lire pour moi. N'a jamais été.

Si c'est le ? et : cela dérange les gens, je serais également satisfait de toute syntaxe alternative à une seule ligne.

Cette construction à une seule ligne fonctionne pour les valeurs initiales non calculées. Un moyen d'étendre cela aux valeurs initiales calculées serait formidable.

v := a; if t { v = b }        // non-computed initial value

v := f(); else if t { v = b } // f() not evaluated where t==true

Malheureusement, _go fmt_ détruit de nombreuses constructions à une seule ligne utiles. Je n'utilise pas _go fmt_ pour cette raison ; le code compact lisible télescopique le rend moins lisible. Mais c'est tangentiel.

Cette fonctionnalité est réalisable sans opérateur ternaire si Go 2 ajoute des génériques

func ternary(type T)(cond bool, vTrue, vFalse T) T { 
    if cond { return vTrue } else { return vFalse }
}

Bien sûr, l'utiliser ne serait pas joli, surtout s'il y avait plus d'un appel ternary .

Quant à l'évaluation, il peut s'agir d'une optimisation au niveau du compilateur.

Cette fonctionnalité est réalisable sans opérateur ternaire si Go 2 ajoute des génériques

func ternary(type T)(cond bool, vTrue, vFalse T) T { 
    if cond { return vTrue } else { return vFalse }
}

Bien sûr, l'utiliser ne serait pas joli, surtout s'il y avait plus d'un appel ternary .

Quant à l'évaluation, il peut s'agir d'une optimisation au niveau du compilateur.

Hum non, vTrue et vFalse seront toujours évalués, je veux dire

ternary(3>2, func1(), func2())

provoquera l'appel de func1() et func2(). Aucun compilateur ne peut savoir que func2() n'a pas besoin d'être évalué... et il ne devrait jamais supposer que de toute façon, car c'est un principe fondamental que dans un appel de fonction, les arguments doivent toujours être évalués, avant l'appel de la fonction lui-même. Si func2() fait des choses en plus de renvoyer une valeur, nous voulons que ces choses soient faites, sinon ce serait très imprévisible et difficile à comprendre.

(Contrairement à un opérateur ternaire réel où la valeur de false n'est pas censée être évaluée par principe.)
```

Cette fonctionnalité est réalisable sans opérateur ternaire si Go 2 ajoute des génériques

func ternary(type T)(cond bool, vTrue, vFalse T) T { 
    if cond { return vTrue } else { return vFalse }
}

Bien sûr, l'utiliser ne serait pas joli, surtout s'il y avait plus d'un appel ternary .
Quant à l'évaluation, il peut s'agir d'une optimisation au niveau du compilateur.

Hum non, vTrue et vFalse seront toujours évalués, je veux dire

ternary(3>2, func1(), func2())

provoquera l'appel de func1() et func2(). Aucun compilateur ne peut savoir que func2() n'a pas besoin d'être évalué... et il ne devrait jamais supposer que de toute façon, car c'est un principe fondamental que dans un appel de fonction, les arguments doivent toujours être évalués, avant l'appel de la fonction lui-même. Si func2() fait des choses en plus de renvoyer une valeur, nous voulons que ces choses soient faites, sinon ce serait très imprévisible et difficile à comprendre.

(Contrairement à un opérateur ternaire réel où la valeur de false n'est pas censée être évaluée par principe.)

Alors la signature serait comme ça :

func ternary(type T)(cond bool, vTrueFunc, vFalseFunc func() T) T { 
    if cond { return vTrueFunc() } else { return vFalseFunc() }
}

Je dois admettre cependant que cette implémentation est très moche :(

Il y a eu des commentaires supplémentaires depuis que nous avons déclaré qu'il s'agissait d'un déclin probable (https://github.com/golang/go/issues/33171#issuecomment-525486967), mais pour autant que nous sachions, aucun d'entre eux n'a dit quoi que ce soit de vraiment nouveau. Nous convenons qu'il existe des cas où la syntaxe ?: serait pratique, mais dans l'ensemble, cela ne semble pas valoir la peine d'être ajouté au langage.

-- pour @golang/proposal-review

La décision est donc basée sur "ne semble pas valoir la peine d'être ajouté" ?
Je ne suis pas du tout surpris... Les expressions ternaires détruiraient la "pureté" de la langue, n'est-ce pas ?

Les changements de langue sont toujours un compromis coût-bénéfice. Il y a rarement une réponse univoque.

Il n'y a pas d'explication simple concernant l'absence de période d'opérateur ternaire.

À première vue, le refus de mettre en œuvre cette caractéristique de base revient à dire que les vélos peuvent être dangereux s'ils sont rapides et à refuser de fabriquer un vélo avec des vitesses élevées en conséquence. Certains peuvent se mêler de la question de savoir si les architectes de langage de Go ont raison ou tort, mais je préférerais monter à un niveau d'abstraction et déterminer si les langages doivent associer les problèmes de fonctionnalités aux problèmes de maintenabilité :

Si la fonctionnalité X pouvait être utilisée de manière abusive et aboutir à un nid de rats de code, est-ce une raison suffisante pour que la fonctionnalité X soit exclue du langage ?

Je dirais que c'est peut-être le cas, mais pas en soi : cela doit être mis en balance avec la demande et la difficulté. Si une fonctionnalité est très demandée et facile à mettre en œuvre, il serait préférable de dissocier les problèmes en implémentant la fonctionnalité et en présentant un moyen de l'interdire, voire de l'interdire par défaut.

En fait, si la demande est suffisamment élevée, même la difficulté est une mauvaise raison de la refuser. Considérez la syntaxe class en Javascript (ES2015) : les architectes du langage ne voulaient vraiment pas ajouter la fonctionnalité, et c'était en fait un peu de travail pour ajouter la syntaxe, mais la demande était incroyablement élevée. Qu'ont-ils fait? Ils ont ajouté la syntaxe, sachant très bien que toute organisation qui ne voulait pas de la fonctionnalité pouvait facilement interdire la syntaxe au niveau du lint.

C'est la résolution appropriée pour l'opérateur ternaire, compte tenu de la demande. Découpler ces préoccupations est approprié, et les résoudre de manière plus configurable serait le plus logique. La même chose devrait se produire pour des choses comme les erreurs de "variable inutilisée" qui font des problèmes de peluchage des crises "arrêtez les presses dont vous avez besoin pour résoudre ce problème avant que le programme ne s'exécute". (Oui, je sais qu'il existe une solution _ , mais c'est toujours juste que cela devrait être configurable)

C'est une erreur de penser qu'un langage devrait être le produit d'un petit nombre d'architectes qui connaissent mieux sans un lien profond avec ceux qui utilisent réellement le langage. L'appel à des données pour prouver que les architectes du langage ont tort est admirable, mais une telle analyse est inutile. Regardez la taille de ce fil : il y a de la demande.

Malheureusement, ignorer la demande est ce qui conduit à des produits concurrents : dans ce cas, c'est ainsi que les langues sont forgées. Vous voulez vous faire fourcher ? (Pour être clair : il s'agit d'une prédiction, pas d'une menace.
Je ne suis certainement pas en train de bifurquer une langue.)

@dash Ce problème est clos, et je ne vais pas le discuter, mais j'aimerais corriger ce que je pense être une fausse déclaration. Vous sous-entendez que Go est un langage qui est "... le produit d'un petit nombre d'architectes qui connaissent mieux _sans lien profond avec ceux qui utilisent réellement le langage_". Ce n'est certainement pas vrai. Tout le monde dans l'équipe Go, et certainement les "architectes", écrivent du code Go tous les jours, et en ont écrit une quantité substantielle depuis 2007. Nous interagissons également avec d'autres utilisateurs Go sur une base presque quotidienne. Nous avons absolument un lien profond avec ceux qui utilisent réellement la langue, c'est-à-dire nous - parmi tant d'autres.

Je ne fais pas partie des architectes, et j'utilise beaucoup le langage, et je rencontre régulièrement des situations où j'utiliserais presque certainement un opérateur ternaire s'il était disponible. Et puis je lis mon code plus tard, et j'y pense, et je suis content qu'il ne soit pas là. YMMV.

Je ne pense pas que rendre des choses comme celle-ci, ou les avertissements de variable inutilisés, "configurables" me faciliterait la vie en tant que développeur ; Je pense que cela rendrait ma vie de développeur plus difficile.

Je ne suis pas non plus l'un des architectes, et j'utilise aussi beaucoup le langage, et je rencontre régulièrement des situations où j'utiliserais presque certainement un opérateur ternaire s'il était disponible. Et puis j'ai lu mon code plus tard, et je maudis les quelques personnes qui nous refusent cette fonctionnalité utile !

Pareil ici, j'utilise Go tous les jours et j'en aurais besoin tous les jours et je suis convaincu que cela rendrait mon code plus clair et encore plus robuste.

Au fait, dans la proposition de "Reword FAQ answer"

utilisation d'un opérateur ternaire au lieu d'une instruction conditionnelle (et non d'une expression) par souci de brièveté ;

La "brièveté" est mentionnée comme si c'était une mauvaise chose. La brièveté aide à la lisibilité. L'idée même d'un code lisible est qu'il va « droit au but » de ce qu'il fait réellement. Ce n'est pas comme affecter 8080 ou -1 au port, puis 80 plus tard dans le code parce que c'est la production.

Je pense qu'il y a peu de chance maintenant que Go obtienne un opérateur ternaire, non seulement parce que l'équipe Go s'y est toujours opposée, mais parce que (à en juger par le vote emoji) environ 60% de la communauté est également contre.

Cependant, si Go finit par obtenir des génériques, je pense que l'équipe devrait sérieusement envisager d'ajouter une fonction ternaire à la bibliothèque standard, même s'il n'y aura pas de court-circuit, sauf peut-être par le biais d'une optimisation du compilateur.

S'ils ne le font pas, alors les 40% qui sont en faveur d'une sorte d'opérateur/fonction termique (moi y compris) écriront immédiatement le leur. Cela créera un cauchemar de lisibilité et de maintenance car différents noms seront choisis (Cond, Iff, Iif, Pick, Choose, Tern etc.) et ils seront dans des packages avec des noms différents.

S'il est ajouté à la bibliothèque standard à la place, cette fragmentation ne se produira pas car tous ceux qui sont en faveur utiliseront la version standard et ceux qui ne l'aiment pas sauront au moins ce qu'elle fait.

func ifThen(condition bool, ifTrue,ifelse interface{}) interface{}{
si état {
retourner si vrai
} autre {
retour sinon
}
}

Il me semble que cette discussion concernant l'opérateur ternaire dans certains cas se résume à une "solution à un problème différent".

L'absence de valeurs par défaut dans les fonctions fait que les gens écrivent du code comme suit :

if elementType == "" {
    elementType = "Whatever"
}
//  times X ...

avec des gens qui veulent simplement ceci comme :

elementType = elementType == "" ? "Whatever" : elementType
// times X ...

Ou

func DoDesign( elementType string = "Whatever" )

Ainsi, un opérateur ternaire essaie de résoudre un problème, qui est lié à un autre problème. Alors que la version Go plus standard est en effet plus lisible, elle devient moins lisible lorsque vous avez affaire à 4 ou 5 d'entre eux à la suite.

Il faut également se demander si la lisibilité est servie lorsque les gens commencent à construire de plus en plus leurs propres "solutions" comme le montre @ArnoldoR . L'un des problèmes qui a tourmenté Javascript est la croissance des "solutions" pour les fonctionnalités manquantes, ce qui a conduit certains projets à importer des packages NPM à gauche et à droite. Les packages populaires comme SqlX sont davantage un signe de fonctionnalités manquantes dans Go.

La lisibilité est une chose. Mais devoir écrire parfois 20 lignes qui sont plus ou moins contenues dans 5 lignes. Il s'accumule sur n'importe quel projet.

Si le problème est que le ternaire peut être utilisé à mauvais escient pour créer du code illisible, en particulier des opérateurs ternaires imbriqués, alors mettez-y une limite. Je pense que la plupart des gens dans ce sujet n'auront aucun problème si un opérateur ternaire est limité à un seul "niveau" et que le compilateur vous empêche d'utiliser des opérateurs de niveau profond.

Nous savons que les gens vont abuser des génériques pour les mettre en œuvre de toute façon. Alors pourquoi ne pas fournir une version officielle, vous pourrez alors en limiter les abus. Mais ces fonctions sauvages, comme nous le voyons ci-dessus, ne feront que gagner en popularité avec le temps, comme nous l'avons vu dans la communauté Javascript. Et quand le génie quitte la bouteille, il n'y a plus de contrôle.

Cette page vous a été utile?
0 / 5 - 0 notes