Steve Palley
Steve Palley

Reputation: 315

Swift 1.2 "Cannot express tuple conversion" error

This method was working fine in the last stable version of Swift, but it won't compile in Swift 1.2:

  final func rotateBlocks(orientation: Orientation) {
    if let blockRowColumnTranslation:Array<(columnDiff: Int, rowDiff: Int)> = blockRowColumnPositions[orientation] {
        for (idx, (columnDiff:Int, rowDiff:Int)) in enumerate(blockRowColumnTranslation) {
            blocks[idx].column = column + columnDiff
            blocks[idx].row = row + rowDiff
        }
    }
}

This line:

for (idx, (columnDiff:Int, rowDiff:Int)) in enumerate(blockRowColumnTranslation) {

Throws the following error:

"Cannot express tuple conversion "(index:Int, element:(columnDiff:Int,rowDiff:Int)) to "(Int, (Int, Int))"

Any ideas about what's going on here, and how to fix it?

Upvotes: 2

Views: 1425

Answers (5)

HZY
HZY

Reputation: 1

final func rotateBlocks(orientation: Orientation) {
    if let blockRowColumnTranslation = blockRowColumnPositions[orientation] {
        for (idx, diff) in enumerate(blockRowColumnTranslation) {
            blocks[idx].column = column + diff.colunmDiff
            blocks[idx].row = row + diff.rowDiff
        }
    }
}

Upvotes: -1

hert
hert

Reputation: 1042

I ran into the same thing and was able to get this working by adding an element: label for the tuple:

for (idx, element: (columnDiff: Int, rowDiff: Int)) in enumerate(blockRowColumnTranslation) {
    blocks[idx].column = column + element.columnDiff
    blocks[idx].row = row + element.rowDiff
}

Upvotes: 3

Steve Palley
Steve Palley

Reputation: 315

Thanks guys! I wound up just rewriting it as a for-loop.. it's not exciting but it seems to work okay:

  final func rotateBlocks(orientation: Orientation) {

    if let blockRowColumnTranslation:Array<(columnDiff: Int, rowDiff: Int)> = blockRowColumnPositions[orientation] {

        for var idx = 0; idx < blockRowColumnTranslation.count; idx++
            {
            let tuple = blockRowColumnTranslation[idx]
            blocks[idx].column = column + tuple.columnDiff
            blocks[idx].row = row + tuple.rowDiff
        }
    }
}

Upvotes: 0

BaseZen
BaseZen

Reputation: 8718

I would use typealias to simplify, but the following compiles without error for me.

var row: Int = 0
var column: Int = 1
struct block {
    var column: Int
    var row: Int
}
var blocks = [block]()

enum Orientation { case Up; case Down; }
typealias Diff = (columnDiff: Int, rowDiff: Int)
typealias DiffArray = Array<Diff>
typealias DiffArrayDict = [Orientation: DiffArray]

var blockRowColumnPositions = DiffArrayDict();

func rotateBlocks(orientation: Orientation) {
    if let blockRowColumnTranslation: DiffArray = blockRowColumnPositions[orientation] {
        for (idx, diff) in enumerate(blockRowColumnTranslation) {
            blocks[idx].column = column + diff.columnDiff
            blocks[idx].row = row + diff.rowDiff
        }
    }
}

Upvotes: 3

Airspeed Velocity
Airspeed Velocity

Reputation: 40955

Looks like a Swift bug to me. More generally, this is busted:

let pair = (a: 1, b: 2)
// normally those named elements don't matter, this is fine:
let (x,y) = pair
// but add a bit of nesting:
let indexed = (index: 1, pair)
// and, error: 
let (i, (x,y)) = indexed
// cannot express tuple conversion '(index: Int, (a: Int, b: Int))' to '(Int, (Int, Int))'

I'd try removing the type names from the array's tuple declaration (i.e. Array<(Int,Int)> instead of Array<(columnDiff: Int, rowDiff: Int)>), see if that helps.

In other, perhaps related, news, this appears to crash the 1.2 compiler:

let a: Array<(Int,Int)> = [(x: 1,y: 2)]

Upvotes: 1

Related Questions