2

When trying the following in the playground, I get the following error:

Cannot invoke 'sort' with an argument list of type '([Int], (Int, Int) -> Bool)'

let stuff = [1, 2, 3]
var sortedStuff = sort(stuff, { (left: Int, right: Int) -> Bool in left < right })

Am I doing something wrong?

Vkt0r
23.5k15 gold badges86 silver badges102 bronze badges
asked Aug 25, 2014 at 20:54
1
  • Wow... Apple still hasn't updated their iBook... I just harassed them about it on Twitter, so hopefully they'll fix it... we'll see. Commented Oct 1, 2014 at 23:39

1 Answer 1

7

sort() sorts an array in-place:

var stuff = [3, 2, 1]
sort(&stuff, { (left: Int, right: Int) -> Bool in left < right })
println(stuff) // [1, 2, 3]

The first argument of sort() must be the address of a variable array (and it does not return a value). This causes the (misleading) error message, as you are passing an array as the first argument.

What you probably want to use is sorted(), which does not modify the original array and returns a new sorted array:

let stuff = [3, 2, 1]
var sortedStuff = sorted(stuff, { (left: Int, right: Int) -> Bool in left < right })
println(stuff) // [3, 2, 1]
println(sortedStuff) // [1, 2, 3]

The function names have changed in one of the earlier beta releases, as mentioned in release notes

Important Changes, Issues Resolved in Xcode 6 beta 1–3
...
The global sort function now mutates its first argument, and a new sorted function always returns a new collection.

so some tutorials may be out-of-date. The Swift books however are regularly updated, so you might want to download a current version.

As mentioned in the comments, you can shorten the closure notation in various ways:

let sortedStuff = sorted(stuff, { left, right in left < right }) // Inferring type from context
let sortedStuff = sorted(stuff, { 0ドル < 1ドル }) // Shorthand argument names
let sortedStuff = sorted(stuff, <) // Using an operator function

All this is described in detail in the "Closures" chapter of the Swift book.


Update for Swift 2 (Xcode 7): Returning a sorted array is called "sort" again, but it is a (protocol extension) method now instead of a global function:

let stuff = [3, 2, 1]
let sortedStuff = stuff.sort(<)
print(sortedStuff) // [1, 2, 3]

and sorting an array in place has been renamed to "sortInPlace":

var stuff = [3, 2, 1]
stuff.sortInPlace(<)
print(stuff) // [1, 2, 3]
answered Aug 25, 2014 at 21:00
4
  • Also shorthand: sort(&stuff) { 0ドル < 1ドル } and var sortedStuff = sorted(stuff) { 0ドル < 1ドル } where $x revers to the left and right by position by index. Commented Aug 25, 2014 at 21:05
  • Even-shorter-hand: sort(&stuff, <) or sorted(stuff, <). You can pass a function or method anywhere a closure is expected, and that includes standard library functions and operators. Commented Aug 25, 2014 at 22:09
  • Also, since the answer isn't 100% clear on this: the reason your code doesn't work is that you're calling sort (which returns nothing) instead of sorted (which returns an array). The compiler is giving you the wrong error message (it's obliquely trying to tell you that the expected return type of your function call is not the type of the variable you're assigning it to) -- filing a bug would be a good idea. Commented Aug 25, 2014 at 22:12
  • 1
    @rickster: Assigning the void return value of sort() to a variable causes only a warning. The error is that sort() is called with a (constant) array instead of the address of a variable array. - Thanks to both of you for the feedback, I have tried to improve the answer. Commented Aug 26, 2014 at 5:07

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.