What Does $0 Represent in Closures in Swift

What does $0 and $1 mean in Swift Closures?

$0 is the first parameter passed into the closure. $1 is the second parameter, etc. That closure you showed is shorthand for:

let sortedNumbers = numbers.sort { (firstObject, secondObject) in 
return firstObject > secondObject
}

What does $0 represent in closures in Swift?

It's a shorthand argument name.

From the Swift Book:

“Swift automatically provides shorthand argument names to inline
closures, which can be used to refer to the values of the closure’s
arguments by the names $0, $1, $2, and so on.”

— Apple Inc. “The Swift Programming Language.”

It helps reduce the verbosity of your code (sometimes at the cost of readability), so you don't have to write out long argument lists when defining closures.

What does $1 ++ $0 mean in the closure for Swift?

$0 is the first parameter passed into the closure.

$1 is the second parameter.

++ is a custom infix operator

infix operator ++

private func ++<Element>(element: Element, list: ListNode<Element>) -> ListNode<Element> {
return list.insert(element: element)
}

It will insert the element on the right to list on right of the operator

What does $0.1, $0.0, etc. mean in Swift?

$0 is a shorthand name for first argument passed to closure. In this case, as you're mapping a Dictionary, that argument is a tuple - hence $0.0 is a key, and $0.1 is a value

For more info on shorthand argument names, see Swift documentation on closures

Swift: Can someone explain this syntax `numbers.sort { $0 $1 }` for me?

@the_UB and @moonvader are both right, but I just thought that I would extend the example from @moonvader a bit, just to show you how we end up with $0 > $1

If you look at the example in "The Swift Programming Language" about Closure Expressions you can see that to sort an array you call the sort method which can then take a function as a parameter.

This function must take two parameters and compare them, and then return a boolean.

So if we have this array:

let numbers = [4, 6, 8, 1, 3]

and this method

func sortBackwards(val1: Int, val2: Int) -> Bool {
print("val1: \(val1) - val2: \(val2)" )
return val1 > val2
}

We can sort the elements like so:

numbers.sort(sortBackwards) //gives us [8, 6, 4, 3, 1]

The sort method will use our sortBackwards method on each of the elements in the array and compare them.

Here's the output of the print

val1: 6 - val2: 4
val1: 8 - val2: 4
val1: 8 - val2: 6
val1: 1 - val2: 4
val1: 3 - val2: 1
val1: 3 - val2: 4

OK, let's reduce that.

Instead of defining a function, we can add that directly as a parameter to the sort method like so:

numbers.sort({(val1: Int, val2: Int) -> Bool in
return val1 > val2
})

And we still end up with [8, 6, 4, 3, 1] (how fortunate!)

OK, the next thing we can do is what in "The Swift Programming Language" (the link above) is called "Infering Type From Context". As we call this method on an array of Ints, Swift can figure out that our val1 and val2 parameters must be Ints too, there's no need for us to tell it. So, lets remove the types. That leaves us with:

numbers.sort({val1, val2 in
return val1 > val2
})

And still the same result.

OK, getting there. The next thing we can do is what in the book is called "Implicit Returns from Single-Expression Closures"

As our comparison can be done in one line there's no need for us to use return. So:

numbers.sort({val1, val2 in val1 > val2})

Still gives us [8, 6, 4, 3, 1]

Finally we're getting to what @moonvader used much much less words to explain :-) namely "Shorthand Argument Names"

As it says in the book:

Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names $0, $1, $2, and so on.

So, in our example, val1 can be replaced by $0 and val2 can be replaced by $1

Which gives us:

numbers.sort({$0 > $1})

And still we get [8, 6, 4, 3, 1]

We can then continue to use a "Trailing Closure", which means that if the last parameter of a function is a closure, we can add that parameter "outside" the function.

So we end up with:

numbers.sort{$0 > $1}

And the outcome is still [8, 6, 4, 3, 1]

Hope that helps to clarify things.

Contextual closure type '() - Text' expects 0 arguments, but 1 was used in closure body

You have two closures, so $0 from first one (even if it would be correct, but with _ in you just ignore it) is not available in second one.

The fix is to use argument explicitly, like

ForEach(1..<18) { index in   // << here !!
NavigationLink(destination: chapterrun()) {
Text("Chapter \(index)") // << here !!
}
}


Related Topics



Leave a reply



Submit