2015-02-08 388 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!")