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)]].
Related
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.
I am new to spark using scala and very much confused by the notations (x,y) in some scenarios and x._1, y._1. Especially when they are used one over the other in spark transformations
could someone explain is there a specific rule of thumb for when to use each of these syntaxes
Basically there are 2 ways to access a tuple parameter in anonymous function. They're functionally equivalent, use whatever method you prefer.
Through the attributes _1, _2,...
Through pattern matching into variable with meaningful name
val tuples = Array((1, 2), (2, 3), (3, 4))
// Attributes
tuples.foreach { t =>
println(s"${t._1} ${t._2}")
}
// Pattern matching
tuples.foreach { t =>
t match {
case (first, second) =>
println(s"$first $second")
}
}
// Pattern matching can also written as
tuples.foreach { case (first, second) =>
println(s"$first $second")
}
The notation (x, y) is a tuple of 2 elements, x and y. There are different ways to get access to the individual values in a tuple. You can use the ._1, ._2 notation to get at the elements:
val tup = (3, "Hello") // A tuple with two elements
val number = tup._1 // Gets the first element (3) from the tuple
val text = tup._2 // Gets the second element ("Hello") from the tuple
You can also use pattern matching. One way to extract the two values is like this:
val (number, text) = tup
Unlike a collection (for example, a List) a tuple has a fixed number of values (it's not always exactly two values) and the values can have different types (such as an Int and a String in the example above).
There are many tutorials about Scala tuples, for example: Scala tuple examples and syntax.
I have the following code:
def findNonEqualTuples(value: String): List[(Char, Char)] = {
val result = ListBuffer((Char,Char))
for (current <- 0 until value.length / 2) {
if (!value.charAt(current).equals(value.charAt(value.length - 1 - current))) {
val tuple = (value.charAt(current), value.charAt(value.length - 1 - current))
result += tuple
}
}
return result.toList
}
The line result += tuple says "Type mismatch, expected: (Char.type, Char.type) actual: (Char, Char)". I am quite new to scala. Could someone explain what is the difference between these two types and how I fix it?
Your problem is in how you declare the result ListBuffer. Try:
val result = ListBuffer[(Char,Char)]()
Square-bracket notation is used for specifying parameter types. The compiler's interpretation of your code is that you want to create a new ListBuffer initialised to contain the tuple (Char, Char), that is, a tuple containing the Char type (more accurately, as noted by #LuigiPlinge, it is the Char companion object - paired with itself) - hence the mismatch error.
EDIT - addressing the question in your comment:
this is a different type of braces issue :)
The key is to remember that even operators in Scala are in fact method calls,
so that result += (...) is actually sugar for:
result = result.+(...) // since "op=" is sugar for x = x op ...
ie. calling the += method with the arguments contained within the parentheses. So, to pass a single argument consisting of a tuple, we need an extra set of parentheses:
result += ((value.charAt(current), value.charAt(value.length - 1 - current)))
The outer parentheses delimit the method's parameter list, while the inner parentheses encapsulate the tuple.
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
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.