2015-02-08 387 views
5

如何將控制權轉移到Swift代碼中的特定行中?替換Swift中的goto語句

在Objective-C我會做類似下面,使用goto

if(a==b) 
{ 
    goto i123; 
} 
else 
{ 
    goto i456; 
} 
NSLog(@"the not reachable point"); 
i123: 
NSLog(@"line 123 is here"); 
int j = 5; 
int x = 2+j; 
i456: 
NSLog(@"line 456 is here"); 

唯一的控制轉移語句斯威夫特我能找到的是continuebreakfallthrough,並return

continuebreak只適用於循環; returnfallthrough不以這種方式傳輸控制權。

我能用什麼?

編輯: -

朱利安__的回答實際上並沒有解決我的問題,但它可能是唯一的選擇現在。所以我已經接受了Julien的回答_

+9

OMG。當然有些情況下goto很好。但通常你的代碼看起來像50年代的FORTRAN。 – 2015-02-08 18:34:26

+2

這很容易導致未定義的行爲,例如如果在跳轉到'i456:'後使用'x'的值。 Swift語言的一個目標是*編譯器*可以檢查所有變量是否在被使用之前被初始化。 – 2015-02-08 18:53:20

+1

我會說「使用功能」。 'goto'最初是一個沒有子程序的程序的解決方法。 – Sulthan 2016-01-24 19:47:41

回答

4

也許一個switch語句?

switch (a==b){ 
default: 
    NSLog(@"the not reachable point"); 
    fallthrough­ 
case true: 
    NSLog(@"line 123 is here"); 
    int j = 5; 
    int x = 2+j; 
    fallthrough­ 
case false: 
    NSLog(@"line 456 is here"); 
} 

編輯:這裏是你如何可以倒退。

let START = 0 
let STOP = -1 
var label = START 

while(label != STOP){ 
    switch (label){ 

    default: 
     label = START­ 

    case START: 
     NSLog(@"the not reachable point"); 
     if a==b { 
      label = 123 
     } else { 
      label = 456 
     } 

    case 123: 
     NSLog(@"line 123 is here"); 
     int j = 5; 
     int x = 2+j; 
     fallthrough­ 

    case 456: 
     NSLog(@"line 456 is here"); 
     fallthrough 

    case STOP: 
     label = STOP 
    } 
} 

將您的代碼包裝在一個巨大的(但是組織良好的)switch語句中。你甚至可以創建一個名爲goto的函數來修改標籤var的值。

+2

爲什麼-1?你能否至少給出一個理由? – 2015-02-08 18:39:05

+0

實際上,我在客觀中的原始代碼大約是1500行,其中我非常頻繁地使用goto語句。我只用我的問題代碼作爲例子。順便說一句,我已經考慮過開關了。但問題在於,當我使用goto語句時,它會失敗。 – 2015-02-08 18:45:32

+0

恕我直言,這個解決方案是正確的。而且我會加入它。 – 2015-02-08 18:46:07

1

這是怎麼回事?

var j : Int? 
var x : Int? 

if a == b { 
    println("line 123 is here") 
    j = 5 
    x = 2 + j! 
} 
println("line 456 is here") 
+0

爲什麼downvote? – 2015-02-08 18:39:34

+1

可能因爲這不能回答問題(如何將控制權轉移到特定行?)。這只是針對這種特定情況的解決方法。 – 2015-02-08 18:44:14

0

看起來好像Swift不希望任何人使用goto語句。可能要避免將來難以遵循的意大利麪代碼。

一個可能的選擇是使用函數。函數的名稱具有含義,比單純的行號更易於理解。

0

這裏是一個閉合({...}())做法:

let done = false 
while !done { 
    { 
     for formantA in editedFormants { 
      for formantB in editedFormants { 
       if abs(formantA - formantB) < MIN_DISTANCE { 
        let newFormant = (formantA + formantB)/2 
        editedFormants.removeAtIndex(editedFormants.indexOf(formantA)!) 
        editedFormants.removeAtIndex(editedFormants.indexOf(formantB)!) 
        editedFormants.append(newFormant) 
        editedFormants = editedFormants.sort() 
        return 
       } 
      } 
     } 
     done = true 
    }() 
} 
0

我相信你的代碼可以重構爲避免使用goto語句。或者,您可以在函數內使用函數,並仍然可以訪問外部參數。例如,

func foobar(a: Int, b: Int) { 

    func i123() { 
     let j = 5 
     let x = 2+j 
     print("i123 x=\(x) b=\(b)") 
    } 

    func i456() { 
     print("i456") 
    } 

    if a == b { 
     i123() 
    } else { 
     i456() 
    } 
} 
0

爲子孫後代着想:

  • 文章goto in Swift清楚地體現瞭如何實現goto風格的功能,其中包括爲什麼使用它們警告和一個理由的在語言中缺席。

  • 本文作者還提供了GitHub上名爲Goto.swift的Swift包。

0

在可用的語言中,我不認爲GoTo總是一件壞事。我從來沒有用它來在一個函數中跳躍,跳躍和跳躍。這不會導致混淆。但我喜歡使用GoTo給我一個共同的退出點。下面是我的意思(僞代碼)是這樣的一個例子:

func SomeFunction() -> Bool 
{ 
    var iReturnValue = false; 

    // Do some processing 

    if(SomeCondition == true) 
    { 
     // return true; 
     // No. Instead of having a return statement here. 
     // I'd rather goto a common exit point. 

     iReturnValue = true; 
     goto ExitPoint; 
    } 

    // Do Some More processing 

    if(SomeOtherCondition == SomeResult) 
    { 
     iReturnValue = false; 
     goto ExitPoint; 
    } 

    // 
    // More processing 
    // 

ExitPoint: 
    // By having a common exit point I can do any 
    // cleanup here and I've got a single return point 
    // which I think makes my code easier to read. 

    return iResultValue; 
} 

我知道我可以做到同樣的事情有幾個很好地支撐,但我只是找到一個很好用的後藤讓生活更簡單。

+0

看起來像「警衛」是你想要的。 – 2016-07-18 20:55:31

+0

'guard'?我寧願說'推遲'... – manicaesar 2016-09-18 18:54:10

3

嗯...... Swift實際上支持標籤,它可以用作控制流程但不太靈活。以下代碼來自Swift編程語言:

gameLoop: while square != finalSquare { 
    diceRoll += 1 
    if diceRoll == 7 { diceRoll = 1 } 

    switch square + diceRoll { 
    case finalSquare: 
    // diceRoll will move us to the final square, so the game is over 
     break gameLoop 
    case let newSquare where newSquare > finalSquare: 
    // diceRoll will move us beyond the final square, so roll again 
    continue gameLoop 
    default: 
    // this is a valid move, so find out its effect 
     square += diceRoll 
     square += board[square] 
    } 
} 
print("Game over!")