Ternärer Operator (if else verkürzen)

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Ternärer Operator (if else verkürzen)

    Hi, ich bin neu hier und wollte direkt mal mit einer Frage beginnen :)
    Ich habe mich nun schon öfters mit dem Ternären Operator auseinandergesetzt und immer hinbekommen.
    Jetzt habe ich versucht es nochmal zu machen und irgendwas vergesse ich, das ich es nicht mehr hinbekomme.

    Zunächst mein Code:

    Quellcode

    1. @IBOutlet weak var nameField: UITextField!
    2. @IBOutlet weak var textLabel: UILabel!
    3. @IBAction func nameSafeButton(_ sender: UIButton) {
    4. // die funktionierende if-else anweissung
    5. if nameField.text != nil {
    6. textLabel.text = nameField.text
    7. }
    8. // Die versuchte kürzung
    9. nameField.text! ? (textLabel.text = nameField.text) : nil
    10. }

    Die fehlermeldung:
    :cursing: Result values in '? :' expression have mismatching types '()' and '_'

    Was hab ich vergessen?

    Quellcode

    1. nameField.text! != nil ? textLabel.text = nameField.text : nil

    Funktioniert auch nicht.

    Danke schonmal im vorraus :)
  • Neytex schrieb:

    Ich habe mich nun schon öfters mit dem Ternären Operator auseinandergesetzt und immer hinbekommen.
    Jetzt habe ich versucht es nochmal zu machen und irgendwas vergesse ich, das ich es nicht mehr hinbekomme.
    Auseinandergesetzt und am Rätselraten. Wieso guckst Du dann nicht einfach nach, wie das funktioniert???

    The Swift Programming Language - Operator runterscrollen zu Ternary Conditional Operator
  • Neytex schrieb:

    Zunächst mein Code:

    Quellcode

    1. @IBOutlet weak var nameField: UITextField!
    2. @IBOutlet weak var textLabel: UILabel!
    3. @IBAction func nameSafeButton(_ sender: UIButton) {
    4. // die funktionierende if-else anweissung
    5. if nameField.text != nil {
    6. textLabel.text = nameField.text
    7. }
    8. // Die versuchte kürzung
    9. nameField.text! ? (textLabel.text = nameField.text) : nil
    10. }
    In Zeile vier ist im Kommentar von einer if-else Anweisung die Rede. Es gibt aber keinen else-Zweig. Daher ist der Ternäre Operator hier auch generell fehl am Platz.
  • Neytex schrieb:

    Quellcode

    1. // Die versuchte kürzung
    2. nameField.text! ? (textLabel.text = nameField.text) : nil

    Die fehlermeldung:

    Result values in '? :' expression have mismatching types '()' and '_'
    Die Fehlermeldung sagt eigentlich sehr präzise was das Problem ist, aber, da sie zugegeben auch für Fortgeschrittene nur schwer verständlich ist und dabei auch nur ein Teil der Thematik beschreibt, versuche ich das bei dieser Gelegenheit mal ein bißchen aufzudröseln.

    Zum besseren Verständnis versuche ich das mit zusammengestauchten Samplecode zu erklären, den jeder in einem Playground nachvollziehen kann.

    Was Du versucht hast entspricht im Prinzip folgendem:

    Quellcode

    1. var name: String? = "name"
    2. var label: String?
    3. name != nil ? (label = name) : nil
    4. // error: result values in '? :' expression have mismatching types '()' and '_'

    1.) Was bedeutet Typ '_'

    Den Unterstrich verwendet man Swift, wenn man eine Variable oder einen Parameter ignorieren, bzw. verwerfen will. Er stellt einen Wert dar, mit dem nichts geschiet, bzw. nichts geschehen soll.

    Beispiel:

    Quellcode

    1. for (count, _) in ["a", "b", "c"].enumerated() {
    2. print(count)
    3. }
    4. // 0
    5. // 1
    6. // 2

    Die enumerated()-Funktion einer Sequence liefert ein Tuple zurück, das eine fortlaufende Nummer und ein Element der Sequence enthält. In obiger For-Schleife interessiert man sich nicht für das Element, sondern nur für die fortlaufende Nummer. In Swift kann man das mit dem Unterstrich ausdrücken, der sagt "ignoriere diesen Wert. Tue damit nichts."
    Das ist genau das, was in in dem Eingangsproblem mit dem nil passiert. Das steht einfach nur so belämmert in der Landschaft rum, aber damit passiert nichts; keine Rückgabe, keine Zuweisung. Durch die Typeinference ist das nil für den Compiler dann vom Typ 'Ignorieren', bzw. '_'.

    2.) Was bedeutet Typ '()'

    Auch Funktionen haben in Swift einen Typ. Der Typ einer Funktion, die keinen Parameter hat und nichts zurückliefert lautet () -> Void , bzw. verkürzt () -> ().

    Beispiel:

    Quellcode

    1. func doNothing() { }
    2. var emptyFunction = doNothing
    3. print(type(of: emptyFunction)) // () -> ()
    Das (label = name) im Ausgagsproblem ist ein Assignment (eine Zuweisung), letztendlich wie bei einer Funktion ausführbarer Code. Der Rückgabewert dieser Zuweisung ist Void, verkürzt als () dargestellt.


    D.h. der Compiler beschwert sich hier, daß der Typ von "tue etwas, aber liefere nichts zurück" und "ignoriere mich" nicht übereinstimmt.

    Das läßt sich beheben indem man die 'Rückgabewerte' des Ternären Operators vereinheitlicht. Z.B. wäre folgendes OK:

    Quellcode

    1. name != nil ? (label = name) : (label = nil) // OK
    Wie in der Schulmathematik kann man beide Ausdrücke ausklammern ;) :

    Quellcode

    1. label = name != nil ? name : nil
    Das entspricht dann dem Code, den @matz zurecht angeführt hat, und der Dir wahrscheinlich auch im Hinterkopf rumschwebte.

    In Swift läßt sich dieser Ausdruck "Wenn X nicht nil dann X, sonst Y" mittels des speziellen ??-Operators noch einfacher ausdrücken:

    Quellcode

    1. label = name ?? nil
    Und damit kommen wir zum Logigteil, den die Compilermeldung verschweigt. Was ist, wenn label schon einen guten Wert hat und nur geändert werden soll, wenn name einen (neuen) Wert liefert? Ein Überschreiben wäre dann fehl am Platze. Dann würde man es so formulieren:

    Quellcode

    1. label = name ?? label
    Das entspricht dann funktional Deiner ursprünglichen, einfachen if-Abfrage, wobei hier noch explizit ein else-Fall drin steht, den man, worauf @Michael ja schon hingewiesen hat, gar nicht braucht.

    Ein gut optimierender Compiler (Randbemerkung: Der Swiftcompiler ist das verständlicherweise noch nicht an allen Punkten) sollte aus der einfachen ursprünglichen if-Abfrage und einem label = name ?? label wahrscheinlich aber eh den gleichen Code generieren.

    Ich hoffe, ich habe das icht zusätzlich verkompliziert, und das ganze ist etwas klarer geworden.
    Twix heißt jetzt Raider!
  • Vielen dank für die Antworten und die ausführliche erklärung @torquato :)
    Ich habe meinen fehler entdeckt.

    @torquato dein Code:

    Quellcode

    1. name != nil ? (label = name) : (label = nil) // OK
    Das ist was ich auch schon versucht hatte nur ohne die Klammer beim else Teil, folglich hat er trotzdem den Fehler ausgespuckt.
    Dann beim versuch ohne Klammern, habe ich falsch ausgeklammert.
    Aber am meisten bedanke ich mich dafür, das du es so einfach wie möglich beschrieben hast, was diese Fehlermeldung bedeutet.
    Das Hilft mir nun besser zu verstehen, wie ich sowas selbst angehen kann :)

    @manoh
    ich bin nicht an meinem Rechner und ich hatte einen Denkfehler beim ausklammern :)
  • Neytex schrieb:

    @torquato dein Code:

    Quellcode

    1. name != nil ? (label = name) : (label = nil) // OK

    Das ist was ich auch schon versucht hatte nur ohne die Klammer beim else Teil, folglich hat er trotzdem den Fehler ausgespuckt.

    Das ist auch richtig, daß der Compiler dann meckert. Das ist sogar nachvollziehbar, aber für uns normalen Menschen eher schlecht auf Anhieb ersichtlich...
    Dein 'Versuch' sah dann wahrscheinlich sinngemäß so aus:

    Quellcode

    1. name != nil ? label = name : label = nil
    2. // error: result values in '? :' expression have mismatching types '()' and 'String?'
    Bemerke, daß da 'String?' statt '_' am Ende der Fehlermeldung steht.

    Das liegt an den operator precedences, den Rechenregeln, also sowas wie "Punkt- vor Strichrechnung". (HILFE: Man möge mir helfen, wie man das korrekt auf deutsch bezeichnet).

    Der ternäre (Teil-)Operator : ist rechtslastig und höherwertig als der ebenso rechtslastige Zuweisungsopertor =. D.h. der Compiler sieht da nur : label, damit ist der Typemismatch da und das restliche = nil ist dann eh für die Katz und taucht in der Fehlermeldung gar nicht mehr auf.

    Mit Klammern kann man das leicht beheben und auf Nummer Sicher gehen. Ich klammere da gerne lieber zuviel, als mich durch kryptische Doku zu wälzen, welcher exotischer Operator jetzt zuerst ausgewertet wird... Ernsthaft. Das kann man sich doch nicht für jede Sprache merken!

    Man muß jetzt aber auch nicht soooo tief darin rumstochern. Merk Dir einfach Question ? Yes-Result : No-Result und dann klappt das schon. Der ternäre Operator ist nur dazu da, Code etwas kompakter darzustellen. Intern wird das genauso wie z.B. auch bei switch-Abfragen in einfaches if-else umgewandelt. Letztendlich geht es also nur um einen Code-Beauty-Contest... ;)
    Twix heißt jetzt Raider!
  • NSObject schrieb:

    torquato schrieb:

    wie "Punkt- vor Strichrechnung". (HILFE: Man möge mir helfen, wie man das korrekt auf deutsch bezeichnet).
    Ich glaube Operatorenpriorität.
    Ah. Danke. Ja. Das wäre eine passende, typisch deutsche Wortschöpfung. Eine Google-Suche nach dem Begriff (inklusive Anführungsstriche) "Operatorenpriorität" ist sehr (sehr!) Fortran-lastig. :)

    Ich finde es oft schwierig, zwischen den (mir) bekannten englischen Fachtermini und deutschen Äquivalenten rumzustochern, wenn man was verständlich und vielleicht sogar laienhaft ausdrücken will...
    Twix heißt jetzt Raider!
  • torquato schrieb:

    Ah. Danke. Ja. Das wäre eine passende, typisch deutsche Wortschöpfung. Eine Google-Suche nach dem Begriff (inklusive Anführungsstriche) "Operatorenpriorität" ist sehr (sehr!) Fortran-lastig. :)
    Ich finde es oft schwierig, zwischen den (mir) bekannten englischen Fachtermini und deutschen Äquivalenten rumzustochern, wenn man was verständlich und vielleicht sogar laienhaft ausdrücken will...
    Exakt das war das Thema gestern in einem Gespräch. Mein Paradebeispiel bei technischen Termini: "Farbunterabtastung". ^^

    MyMattes schrieb:

    Deutsch ist anders :D
    Kindergarden! Suomi, das ist wirklich anders. ^^

    MyMattes schrieb:

    Ihr sucht die Rangordnung der Rechnungsarten, oder?
    Das wars.
    * Kann Spuren von Erdnüssen enthalten.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von NSObject ()

  • MyMattes schrieb:

    torquato schrieb:

    Ah. Danke. Ja. Das wäre eine passende, typisch deutsche Wortschöpfung.
    Deutsch ist anders :D
    Ihr sucht die Rangordnung der Rechnungsarten, oder?

    SCNR, Mattes
    Entschuldigung, aber wenn das Deutsch sein soll, dann doch bitte "Rechnungsartenrangordnung". Wir können im Deutschen doch so schön allen Kram aneinanderpappen. ;)
    scnr
    Twix heißt jetzt Raider!
  • NSObject schrieb:

    MyMattes schrieb:

    Ihr sucht die Rangordnung der Rechnungsarten, oder?
    Das wars.
    IMHO Nein, eher nicht. ?: ist keine Rechnungsart. Das ist eine logische Verbindung.

    In Gedenken an Konrad Zuse wäre das 'wahrlich deutsche' 'Kalkülrangordnung' vermutlich passender. ;)

    Nur, kann man mit so einem Begriff einem Pokemon-Kid wirklich besser erklären, was gemeint ist? :)
    Twix heißt jetzt Raider!
  • torquato schrieb:

    NSObject schrieb:

    MyMattes schrieb:

    Ihr sucht die Rangordnung der Rechnungsarten, oder?
    Das wars.
    IMHO Nein, eher nicht. ?: ist keine Rechnungsart. Das ist eine logische Verbindung.
    Ich meinte nicht, dass das die Antwort war, sondern die Frage.

    torquato schrieb:

    In Gedenken an Konrad Zuse wäre das 'wahrlich deutsche' 'Kalkülrangordnung' vermutlich passender. ;)
    "Rangordnung" wäre mir zu militärisch, dann eher "Kalkülhierarchie".
    * Kann Spuren von Erdnüssen enthalten.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von NSObject ()

  • NSObject schrieb:

    torquato schrieb:

    NSObject schrieb:

    MyMattes schrieb:

    Ihr sucht die Rangordnung der Rechnungsarten, oder?
    Das wars.
    IMHO Nein, eher nicht. ?: ist keine Rechnungsart. Das ist eine logische Verbindung.
    Ich meinte nicht, dass das die Antwort war, sondern die Frage.
    Ah. OK.

    NSObject schrieb:

    torquato schrieb:

    In Gedenken an Konrad Zuse wäre das 'wahrlich deutsche' 'Kalkülrangordnung' vermutlich passender. ;)
    "Rangordnung" wäre mir zu militärisch, dann eher "Kalkülhierarchie".
    Mir wäre 'Hierarchie' ja zu kaiserlich.... ;)
    Twix heißt jetzt Raider!
  • torquato schrieb:

    NSObject schrieb:

    Mein Paradebeispiel bei technischen Termini: "Farbunterabtastung". ^^
    Jetzt mußt Du uns aber auch noch verraten, was man darunter verstehen soll!
    Wenn Farbinformationen als Differenz zu einer monochromen Helligkeitsinformation beschrieben werden. Im Englischen wird das als "chroma subsampling" bezeichnet.
    * Kann Spuren von Erdnüssen enthalten.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von NSObject ()