替换 Swift 中的 goto 语句

Replacement for goto statement in Swift

如何将控制转移到 Swift 代码中的特定行?

在 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");

我能在 Swift 中找到的唯一控制传输语句是 continuebreakfallthroughreturn

continuebreak 仅适用于循环; returnfallthrough 不会以这种方式转移控制权。

我能用什么?

编辑:-

Julien__ 的回答并没有真正解决我的问题,但它可能是目前唯一可用的选项。所以我接受了 Julien__

的回答

也许是 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.

的值

这个呢?

var j : Int?
var x : Int?

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

似乎 Swift 不想让任何人使用 goto 语句。可能是为了避免将来太难理解的意大利面条代码。

一种可能的替代方法是使用函数。函数的名称有意义,比单纯的行号更容易理解。

这是一个闭包({...}())方法:

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
    }()
}

我相信您的代码可以重构以避免使用 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()
    }
}

为了子孙后代:

  • 文章 goto in Swift 清楚地举例说明了如何实现 goto 风格的功能,包括关于为什么 使用它们的警告以及他们在语言中缺席的理由。

  • 文章作者还在 GitHub 上将其作为名为 Goto.swift 的 Swift 包提供。

在可用的语言中,我认为 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;
}

我知道我可以用一些放置得当的牙套来达到同样的效果,但我发现使用得当的 Goto 让生活变得更简单。

嗯..... Swift 实际上支持标签,它可以用作控制流的 goto 但不太灵活。以下代码来自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!")