0

Ich mache etwas wirklich einfaches, nur um sich an Swift gewöhnen (kommt aus objc) - Ich möchte einen gewünschten Knoten in einer verketteten Liste mit einer guard Anweisung und einer switch Anweisung zurückgeben . Ich bin offensichtlich missbrauchen die -Anweisung, weil meine else Klausel ist riesig (es ist, wo meine switch-Anweisung gehalten wird). Vielleicht brauche ich nicht einmal eine switch Erklärung, aber es räumt nur ein bisschen auf.Missbrauch der Wächterstatement zu ersetzen Null Überprüfung

Mein alter Code ist wie folgt:

func getValue (atIndex index: Int) -> T { 
    if count < index || index < 0 { 
     print ("index is outside of possible range") 
    } 
    var root = self.head 
    //  if var root = self.head { 
    if index == 0 { 
     return (self.head?.value)! 
    } 
    if index == count-1 { 
     return (self.tail?.value)! 
    } 
    else { 
     for _ in 0...index-1 { 
      root = root!.next! 
     } 
    } 
    return root!.value 
} 

Ersetzt mit einer guard Anweisung (aber einen Compiler-Fehler bekommen, dass der Schutzkörper nicht durch möglicherweise fallen) - mein Problem ist das, was seit meiner Funktion Rückkehr zurückzukehren, Typ ist <T> (beliebiger Typ).

func getValue (atIndex index: Int) -> T { 
    guard (count < index || index < 0) else { 
     switch true { 
     case index == 0: 
      if let head = self.head { 
       return head.value 
      } 
     case index == count-1: 
      if let tail = self.tail { 
       return tail.value 
      } 
     default: 
      if var currentNode = head { 
       for _ in 0...index-1 { 
        currentNode = currentNode.next! 
       } 
       return currentNode.value 
      } 
     } 
    } 
} 

Ich möchte eine print Anweisung außerhalb meiner guard Anweisung hinzufügen zu sagen, dass der gewünschte Index außerhalb des Bereichs liegt, aber ich muss auch T etwas am Ende der Funktion des Typs zurückzukehren. Das Problem ist, dass außerhalb meiner guard und switch-Anweisung, ich nichts zurückgeben muss.

+3

Ich glaube, Sie die Verwendung von Wachen falsch verstanden habe. Der Zustand, den Sie in die Wache setzen, ist die Voraussetzung für * Erfolg *. Das Zeug, das du in den Körper des Wächters legst, ist der Code, der auf * failure * ausgeführt wird, was zu einer Übertragung der Kontrolle ('return',' throw' usw.) führen muss. Daher sollte der Erfolgscode kurz nach der Wache kommen. Auch das Umschalten von 'true' macht keinen Sinn. Sicheres Umschalten von' index' würde mehr Sinn machen, denn das ist es was du vergleichst? Auch was ist 'T'? Ihre Funktion ist nicht generisch, ist es eine generische Klasse? – Hamish

+0

Als ich versuchte, den Index umzuschalten, wurde mir die Fehlermeldung "Expression Pattern vom Typ 'Bool' kann nicht mit Werten vom Typ 'Int'" übereinstimmen. Die Klasse der verknüpften Listen ist generisch - bei der Instanziierung gebe ich an, um welchen Objekttyp ich den jeweiligen Knotenwert festlegen möchte. –

+0

Sie müssen die möglichen Werte Ihres Indexes als Fälle verwenden, d. H. "Fall 0", "Fallanzahl 1". – Hamish

Antwort

2

Das ist guard Anweisung verwendet, um den ungültigen Fall zu fangen, würden Sie so etwas wie wünschen:

func getValueAtIndex(index: Int) -> T { 
    guard index >= 0 && index < count else { 
     // Invalid case 
     print("Index is outside of possible range") 

     // Guard must return control or call a noreturn function. 
     // A better choice than the call to fatalError might be 
     // to change the function to allow for throwing an exception or returning nil. 
     fatalError("Index out of bounds") 
    } 

    // Valid cases 
} 
+1

Eine einfache 'return' wird hier nicht kompiliert, da die Funktion einen (nicht void) Rückgabetyp hat. –

+1

@MartinR Guter Punkt, wechselte es zu fatalError und fügte eine Notiz hinzu. –

0

A guard Aussage gemeint ist, das Programm aus seinem aktuellen Bereich zu bewegen oder eine noreturn Funktion aufrufen, wenn Ein Wert wird nil gefunden. Sie führen jedoch eine vollständige switch Anweisung in Ihrem guard.

Per Apple's Guard Documentation:

Die else Klausel einer guard Anweisung erforderlich ist, und entweder muss eine Funktion mit dem noreturn Attribut oder Transferprogrammsteuerung außerhalb des Wächters Erklärung des umgebenden Gültigkeitsbereich gekennzeichnet nennen mit einem der folgenden Aussagen:

  • Rückkehr
  • Pause
  • weiter
  • throw

Ein gutes Beispiel für eine guard könnte sein:

var optValue : String? 

guard let optValue = optValue else {return} 
Verwandte Themen