Swift: how to count the number of elements in Tuple - swift

I was wondering if there is a method or function in Swift which can count the number of elements in the tuple.
Reason of question:
I have a tuple called "tople"
What I want to do is to load the elements into variables (by using for loop, where you actually need the number of elements)
And then use this in a function.
Additional questions, can you use tuples to load variables into the function and/or to return them from a function?
var tople = (1,2,3)
func funkce (a:Int, b:Int, c: Int){
println(a)
println(b)
println(c)
}
funkce(a,b,c)
Thanks and I do appreciate any helpful comment.

In Swift 3 you count the number of elements in a tuple like this:
let myTuple = (1,2,3,4)
let size = Mirror(reflecting: myTuple).children.count

Yes, you can load tuples into variables.
let (a, b, c) = (1, 2, 3)
To extract values from a tuple, you can use MirrorType. You can find more here.
let tuple = (1, 2, 3)
let count = Mirror(reflecting: tuple).children.count // 3

Related

Determining type of map output

I am trying to determine what the type of .map's output is here:
func position(rows: Int, cols: Int) -> [Position] {
return (0 ..< rows)
.map {
zip(
[Int](repeating: $0, count: cols) ,
0 ..< cols
)
}
}
I know that zip returns a Zip2Sequence instance, which in this case is tuple pairs of (integer array, countable integer range).
I get that map alters elements in a sequence, but I thought it took multiple arguments like val in val * 2 and here zip is the only argument... so is it just adding the output of zip to an array?
The result of the map is of type Array<Zip2Sequence<Array<Int>, CountableRange<Int>>> which is essentially [[(Int, Int)]].
I found this by assigning the result of the map to let result and printing print(type(of: result)).
map transforms your original sequence (0 ..< rows) into an array that will have rows items. zip will be called with each element of (0 ..< rows) in turn which is represented by $0.
It will be more useful if you wrap the zip call with Array() to turn the zip sequence into an actual array that you can examine easily:
Example:
let rows = 2
let cols = 3
let result = (0 ..< rows)
.map { val in
Array(zip(
[Int](repeating: val, count: cols) ,
0 ..< cols
))
}
print(result)
// [[(0, 0), (0, 1), (0, 2)], [(1, 0), (1, 1), (1, 2)]]
The type of (0 ..< rows) is CountableRange<Int>:
1> (0 ..< 10)
$R0: (CountableRange<Int>) = {
lowerBound = 0
upperBound = 10
}
CountableRange conforms to Sequence, so it has a map method. This map method takes one argument, a closure.
A closure is a function. In general, a function has zero or more arguments and a one return value. For CountableRange<Int>.map, the closure is required to take one argument of type Int and can return any type.
There are several ways to write closures in Swift. The shortest way, which your example uses, is to write a single expression inside { ... }. Here's what The Swift Programming Language (Swift 4) says:
Implicit Returns from Single-Expression Closures
Single-expression closures can implicitly return the result of their single expression by omitting the return keyword from their declaration[…]
Furthermore, if the closure takes arguments, the closure can refer to them using shorthand names ($0, $1, etc.) instead of giving them explicit names (e.g. val in ...). From the book again:
Shorthand Argument Names
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.
If you use these shorthand argument names within your closure expression, you can omit the closure’s argument list from its definition, and the number and type of the shorthand argument names will be inferred from the expected function type. The in keyword can also be omitted, because the closure expression is made up entirely of its body[…]
Looking at the map method call, we can see that its closure contains a single expression (a call to zip) with implicit return, and it uses $0 to refer to its single argument.
The zip function takes two arguments, each of which must be a Sequence, and the zip function returns a Zip2Sequence. In your example, the first argument to zip is [Int](repeating: $0, count: cols), which has type [Int] (or Array<Int>). The second argument to zip is 0 ..< cols, which is another CountableRange<Int>. So the type returned by this call to zip is Zip2Sequence<[Int], CountableRange<Int>>, which is a somewhat inscrutable type that generates tuples (Int, Int).
The type returned by map is an Array containing the values returned by its closure argument. Thus the type returned by map in this case is [Zip2Sequence<[Int], CountableRange<Int>>].
If you want something more scrutable, you can wrap the call to zip in the Array constructor:
func position(rows: Int, cols: Int) -> [[(Int, Int)]] {
return (0 ..< rows)
.map {
Array(zip(
[Int](repeating: $0, count: cols) ,
0 ..< cols
))
}
}
The Array constructor takes any Sequence and turns it into an Array. So the Zip2Sequence<[Int], CountableRange<Int>> is turned into [(Int, Int)], and map produces an Array whose elements are that type, thus producing an array of arrays of pairs of Int, or [[(Int, Int)]].

How to sum all elements in a tuple

In Swift, i.e. a tuple let tp = (2,5,8).
What's the simplest and smartest way to sum it up, other than traditionaly as below?
let sum = tp.0 + tp.1 + tp.2
Your approach is the most straightforward. An alternative is harder to read, but it works, too:
let s = Mirror(reflecting: x).children.map {$1 as! Int}.reduce(0,+)
Mirror(reflecting: x).children obtains a sequence of name-value pairs representing the original tuple. Each element of the sequence is a (String,Any) tuple. map {$1 as! Int} converts this sequence to a sequence of Ints representing tuple element values; reduce(0,+) produces the sum of these values.
You can combine map and reduce in a single expression for something even less readable:
let s = Mirror(reflecting: x).children.reduce(0,{$0.1.value as! Int + $0.0})
Note: It goes without saying that this crashes at runtime for tuples containing values of type other than Int.

Swift enumerate functions. How does it work behind?

The enumerate function returns a tuple for each item in the array composed of the index and the value for that item.
The map function returns an array of elements built from the results of applying a provided transforming closure for each element in the array.
Declaration:
func map<U>(transform: (T) -> U) -> [U]
var numbers = [1, 2, 3]
numbers = map(numbers) { (index, element) in
index + element
} //[1, 3, 5]
That is good. Works.
var numbers = [1, 2, 3]
var result = map(enumerate(numbers)) { (index, element) in
index + element
} //[1, 3, 5]
map expects an array as a first parameter, but I put there the tuple as a result of enumerate fnction.
The question is: WHY IT WORKS?
It works because in addition to array having a map method, there is a map function that takes any kind of SequenceType:
func map<S : SequenceType, T>(source: S, transform: (S.Generator.Element) -> T) -> [T]
This works not just with arrays, but any kind of sequence – strings, ranges, zipped pairs of sequences, and the result of enumerate, which is also a sequence:
// enumerate is a function that takes any kind of sequence, and returns
// an EnumerateSequence object
func enumerate<Seq : SequenceType>(base: Seq) -> EnumerateSequence<Seq>
EnumerateSequence is a type that holds on to another sequence (in your case, the array [1,2,3]) and then when asked to generate an element, generates the next element from it’s contained sequence along with an incrementing number.
You want to look at the following answer: What's the cleanest way of applying map() to a dictionary in Swift?
The map function works on the tuple because it is using the map function from the swift standard library that works on any SequenceType. So it is actually using the index and value of the enumeration, which are the same as the index and element that the map function would use when looking at an array input.

Nice way to assign min max variables / deconstruct an array?

I'm looking for an expression to assign the smallest and largest of 2 numbers to variables.
There are several approaches that work
let a = 2
let b = 1
let (min, max) = (min(a, b), max(a, b))
But I wanted something a bit more flexible, for example
let sorted = [a, b].sorted{$0 < $1}
let (min, max) = (sorted.first, sorted.last)
But it's 2 lines... I was looking for something like:
let (min, max) = [a, b].sorted{$0 < $1}
But that doesn't compile, I think because it's not possible to deconstruct arrays, at least in this way, and there doesn't seem to be a clean/meaningful way to convert it to a tuple.
What am I missing? I know there's somewhere an elegant expression for this.
I’d just do a variant of your (pre-edit) first one:
let (min,max) = a < b ? (a,b) : (b,a)
If you do this a lot, you could wrap this in a generic function to make it a bit neater:
func minmax<T: Comparable>(a: T, b: T) -> (T,T) {
return a < b ? (a,b) : (b,a)
}
Which makes this quite nice and readable at the call site:
let (min,max) = minmax(a, b)

What is a useful example of partial function application in Swift?

I see that Swift offers convenient syntax for declaring curried functions. The manual gives partial function application as an example of where curried function will come in handy.
Can someone give me an example where partial function application can be useful? I know this is a general functional programming concept, but an example in Swift would be most appreciated.
Suppose you frequently want to check a number, i, is a multiple of another value. What it might be a multiple of can change, but the rule for how to determine it is always the same: i % n == 0.
You might write a function like this:
func isMultipleOf(#n: Int, #i: Int) -> Bool {
return i % n == 0
}
isMultipleOf(n: 2, i: 3) // false
isMultipleOf(n: 2, i: 4) // true
However, perhaps you find yourself frequently wanting to use this function with other "high-order" functions – that is, functions that take other functions as arguments, such as map and filter:
let r = 1...10
// use isMultipleOf to filter out the even numbers
let evens = filter(r) { isMultipleOf(n: 2, i: $0) }
// evens is now [2,4,6,8,10]
That use of isMultipleOf looks a little clunky and hard to read, so maybe you define a new function, isEven, in terms of isMultipleOf to make it a bit clearer:
let isEven = { isMultipleOf(n: 2, i: $0) }
isEven(2) // true
isEven(3) // false
let evens = filter(r, isEven)
Now, suppose you declare isMultipleOf a little differently, as a curried function:
func isMultipleOf(#n: Int)(#i: Int) -> Bool {
return i % n == 0
}
isMultipleOf is now a function that takes a number, n, and returns a new function that takes a number and checks if it's a multiple of n.
You can now use it to declare isEven like this:
let isEven = isMultipleOf(n: 2)
Or you could use it directly with filter like this:
let evens = filter(r, isMultipleOf(n: 2))
// just like before, evens is [2,4,6,8,10]