Why does Swift think that my array is a function? - swift

// Complete the miniMaxSum function below.
func birthdayCakeCandles(arr: [Int]) -> Int {
let a = arr.sorted
let highest = a().last!
return 0
}
birthdayCakeCandles(arr: [1, 7, 3, 12, 5])
I tried to create a sorted array "a" from an unsorted array "arr", to solve a problem from HackerRank. But compiler gives following error:
main.swift:5:19: error: function 'a' was used as a property; add () to
call it
let highest = a.last!
^
()
Why does it think, that "a" is a function?

error: function 'a' was used as a property; add () to call it
Swift doesn't think that your array is a function. Xcode just tells you, that sorted is a method and you have to call it with () at the end
let a = arr.sorted()

let a = arr.sorted
Why does it think, that "a" is a function?
Because that is just what it is. sorted is the name of a function. So a is now the sorted function.
What you want is for a to be the result of calling a function. But every function call involves parentheses, e.g. sorted(). You have no parentheses.
In short that line of your code talks about sorted. But it never calls sorted. It just renames it.

arr.sorted evaluates to a method of [Int]. If you want a sorted copy of the array call that method:
func birthdayCakeCandles(arr: [Int]) -> Int {
let a = arr.sorted()
let highest = a.last!
return 0
}
Otherwise, the compiler is right: a contains a function: The sorted method.

I believe what you want to do is the following:
func birthdayCakeCandles(arr: [Int]) -> Int {
return arr.max() ?? 0
}
In your code, a is not an array, it is a function with the following signature () -> [Int], because arr.sorted is an instance method. You can check the type of a variable by Alt + clicking on the variable in Xcode. To execute this function you need to invoke it using (). Which you are doing in the following line. The output of a() is an array of integers, on which you are calling the last property.
If your arr is empty, .last! will cause an error/app crash, since you'd be unwrapping nil (there is no last element in an empty array). This is why in the suggested code above, I've used the nil-coalescing operator ??, which would guarantee that the function would return 0 if the array arr is empty.
For more in-depth reading on instance methods, have a look here.

Related

What is the purpose to make a function which return a function?

I was reading Apple doc about swift .
it has an example in which it made a function which returns a function
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
So here my concern is what are advantages of this practice and when to use it?
and if some one can also help me with concept of "A function can take another function as one of its arguments." than that will be so kind
Thanks in advance
Here's a really common case of this that you use all the time, probably without even realizing it.
Instance methods are really just class methods that return closures.
Take String.hasPrefix for example, which has type (String) -> (String) -> Bool.
So String.hasPrefix takes String argument, which is the instance the instance method will act upon, and returns a closure of type (String) -> Bool.
We would usually get this closure by using a form like "The quick brown fox".hasPrefix, but we can also use String.hasPrefix("The quick brown fox"), which is equivalent.
The result of these expressions is the hasPrefix function, bound to the specific instance (the String "The quick brown fox") that it will act upon.
We can then invoke this closure with another String argument, which tells it what prefix to look for.
Here's what you might typically write:
let result = "The quick brown fox".hasPrefix("The") // => True
Let's break that down into steps (with type annotations added for emphasis on the types at play):
import Foundation
let instance: String = "The quick brown fox"
let desiredPrefx: String = "The"
let staticMethod: (String) -> (String) -> Bool = String.hasPrefix
let boundInstanceMethod: (String) -> Bool = staticMethod(instance)
let result: Bool = boundInstanceMethod(desiredPrefx) // => true
equivalent:
import Foundation
let instance: String = "The quick brown fox"
let desiredPrefx: String = "The"
let boundInstanceMethod: (String) -> (String) -> Bool = instance.hasPrefix
let result: Bool = boundInstanceMethod(desiredPrefx) // => true
The benefit of creating a function that returns a function is that the inner function remembers the environment that it was created in. Typically, when you call a function, the variables within that function end when the function finishes. By returning a function, however, you create what is called a closure, and this allows you to hold on to the environment that the closure was created in, so you can use it over and over again.
There are many benefits to being able to accept a function as a parameter to another function. For example, you could create a filter function that accepts an array as its first argument and another function as its second. Then, you could call your filter function and pass it a function that would check each element of the array to see if it was even, and return a new array that only contains even values. You could also call the same filter function with a function that checks each element of an array to see if it is odd, and return a new array containing only odd numbers. This makes the filter function far more flexible than it would otherwise be, and allows you to get away with writing less code. Instead of writing a new, complex function every time you want to filter the elements of an array, and having to maintain a potential multitude of filter functions, you only have to write one.
I hope this helps.
makeIncrementer() have a function addOne(number: Int)
That is only eccessable with in makeIncrementer()
Out side of makeIncrementer() we can not access addOne(number: Int).

How do you use the map function in Swift?

I'm trying to understand how .map works and all of my searches are returning examples that aren't helping me resolve my issue. From my understanding .map is a cleaner way of performing a for-in loop, the only difference is that .map replaces your original creates a new array and for-in just alters your original arrays values.
Attempt
In the code example below, I'm expecting the .map function to replace my wheels array with new Tire objects whose state properties are all set to .Flat.
This is a playground-ready version of what I'm trying to accomplish in my program:
enum State {
case Ok, Flat
}
class Tire {
var state = State.Ok
init(t: State) {
state = t
}
}
var wheels = [Tire(t: .Ok), Tire(t: .Ok), Tire(t: .Ok)]
wheels = wheels.map { $0.state = .Flat }
Result
error: cannot convert value of type '()' to closure result type 'Tire'
wheels = wheels.map { $0.state = .Flat }
~~~~~~~~~^~~~~~~
Question
In the given situation, how can I set all of my Tire objects states to .Flat using .map?
There are 2 similar key functions which perform similar operations, the basic purpose of which is to take an array and build another array from it:
func map(transform:(R)->T) -> [T] --- Map takes an array of elements of one type and converts it to an array of elements of (potentially) another type, by calling a transform function on each element in turn. So you can convert an array of Int's to an array of strings:
[1, 2, 3, 4].map { "\($0)" } // --> ["1", "2", "3", "4"]
func filter(predicate:(T)->Boolean) -> [T] -- Filter takes an array of elements and converts it to an array of elements of the same type, but only includes those elements for which predicate returns true. So you can filter an array of ints to leave only the even numbers:
[1, 2, 3, 4].filter { $0 % 2 == 0 } // --> [ 2, 4]
There are other variants, such as flatMap which takes [[T]] and turns it into [T] by iterating over the input and array and appending the contents of each array to an output array:
[ [1, 2], [3, 4]].flatMap() // --> [1, 2, 3, 4]
It's also worth nothing that the concept behind map is that, in simplistic terms, it can be used to map any input type to an output type, so you can define:
func <R, T> map(in:R?, transform:(R)->T) -> T?
for example, which would translate any optional input type into an optional output type given a function that translates the base type.
The problem is $0.state = .Flat is an assignment. It does not return a value. Try this:
wheels = wheels.map { w in
w.state = .Flat
return w
}
map does not replace anything. It projects each element from your array to a new array by applying the transformation block. You can choose to assign this new array to the old array, but otherwise it will not alter the original array.

How to handle initial nil value for reduce functions

I would like to learn and use more functional programming in Swift. So, I've been trying various things in playground. I don't understand Reduce, though. The basic textbook examples work, but I can't get my head around this problem.
I have an array of strings called "toDoItems". I would like to get the longest string in this array. What is the best practice for handling the initial nil value in such cases? I think this probably happens often. I thought of writing a custom function and use it.
func optionalMax(maxSofar: Int?, newElement: Int) -> Int {
if let definiteMaxSofar = maxSofar {
return max(definiteMaxSofar, newElement)
}
return newElement
}
// Just testing - nums is an array of Ints. Works.
var maxValueOfInts = nums.reduce(0) { optionalMax($0, $1) }
// ERROR: cannot invoke 'reduce' with an argument list of type ‘(nil, (_,_)->_)'
var longestOfStrings = toDoItems.reduce(nil) { optionalMax(count($0), count($1)) }
It might just be that Swift does not automatically infer the type of your initial value. Try making it clear by explicitly declaring it:
var longestOfStrings = toDoItems.reduce(nil as Int?) { optionalMax($0, count($1)) }
By the way notice that I do not count on $0 (your accumulator) since it is not a String but an optional Int Int?
Generally to avoid confusion reading the code later, I explicitly label the accumulator as a and the element coming in from the serie as x:
var longestOfStrings = toDoItems.reduce(nil as Int?) { a, x in optionalMax(a, count(x)) }
This way should be clearer than $0 and $1 in code when the accumulator or the single element are used.
Hope this helps
Initialise it with an empty string "" rather than nil. Or you could even initialise it with the first element of the array, but an empty string seems better.
Second go at this after writing some wrong code, this will return the longest string if you are happy with an empty string being returned for an empty array:
toDoItems.reduce("") { count($0) > count($1) ? $0 : $1 }
Or if you want nil, use
toDoItems.reduce(nil as String?) { count($0!) > count($1) ? $0 : $1 }
The problem is that the compiler cannot infer the types you are using for your seed and accumulator closure if you seed with nil, and you also need to get the optional type correct when using the optional string as $0.

Optional vs Bound value assigning var from array

I want to check if there is a value in a array and if so assign to a String using a if-left statement:
if let scoreValue = scoreValueArray[element!]{
// do something with scoreValue
}
Error: Bound value in a conditional binding must be of optional type
So tried changing the ! to ? but error persists.
Any input appreciated.
scoreValueArray is an array of strings, where a String value is appended to array if a condition is met, then array is saved to NSUserdefaults.
So element is a int which corresponds to a index in the array, bt only if the index is occupied with a String, so
scoreValueArray[element!]
could return an 'Index out of bounds', hence want to use the if-let.
Although the accepted answer clearly puts why optional binding is not available in the current implementation, it doesn't provide with a solution.
As it is shown in this answer, protocols provide an elegant way of safely checking the bounds of an array. Here's the Swift 2.0 version:
extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
Which you can use like this:
let fruits = ["Apple", "Banana", "Cherry"]
if let fruit = fruits[safe: 4] {
// Do something with the fruit
}
It's not clear what type your scoreValueArray is, but for the sake of this answer, I'm going to assume it's an array of Int.
var scoreValueArray: Array<Int>
Now, if we look the definition of the Array struct, we'll find this:
struct Array<T> : MutableCollectionType, Sliceable {
// other stuff...
subscript (index: Int) -> T
// more stuff
}
So, calling the subscript method on our array (which is what we do when we say scoreValueArray) returns a non-optional. And non-optionals cannot be used in the conditional binding if let/if var statements.
We can duplicate this error message in a more simple example:
let foo: Int = 3
if let bar = foo {
// same error
}
This produces the same error. If we instead do something more like the following, we can avoid the error:
let foo: Int? = 3
if let bar = foo {
// perfectly valid
}
This is different from a dictionary, whose subscript method does return an optional (T?). A dictionary will return a value if the key passed in the subscript is found or nil if there is no value for the passed key.
We must avoid array-index-out-of-bounds exceptions in the same way we always do... by checking the array's length:
if element < scoreValueArray.count {
scoreValue = scoreValueArray[element]
}

Calling functions that use inout arrays from a closure

I decided to update a project that I had made during Swift beta 1 now that Swift 1.0 is out. There's a particular issue, however, that I can't seem to fix that came up as a result of the updated array semantics and inout keyword. Consider the following two functions (you can just paste them into a playground):
func bubbleSort<T : Comparable>(inout arr : [T]) {
var numSwaps = 0
do {
numSwaps = 0
for i in 0..<(arr.count - 1) {
if arr[i] > arr[i + 1] {
(arr[i], arr[i + 1]) = (arr[i + 1], arr[i])
numSwaps++
}
}
} while numSwaps != 0
}
func testFunc(sortFunc: ([Int]) -> ()) {
sortFunc([5,4,3,2,1])
}
I can't seem to make the two work together. I tried using shorthand:
testFunc {bubbleSort(&$0)}
I also tried without shorthand:
testFunc { (arr: [Int]) -> () in
bubbleSort(&arr)
}
In either case, I get errors:
Is this a bug, or am I screwing something up? Thanks in advance!
What you're running into is that method parameters are by default immutable and in-out functions are mutating. You can't use the closure shorthand, because you'll need to declare the closure's argument as mutable with the var keyword, like so:
func testFunc(sortFunc: ([Int]) -> ()) {
sortFunc([5,4,3,2,1])
}
testFunc { (var arr: [Int]) -> () in
bubbleSort(&arr)
}
Now you can call bubbleSort with arr as the in-out parameter.
What you're running into is the change in beta 3 (if I recall correctly) where changing en element of an array became a mutating operation. Before that changing an element was a non-mutating operation, and therefore you can change an element on an Array constant; you just couldn't change its length. But since beta 3, to change an element on an array, it needs to be non-constant.
bubbleSort takes the array by reference (inout) because it needs to change the elements of the array and have it visible to the caller (prior to beta 3, it just took it by value). You can only pass a non-constant variable by reference. In the closure you wrote, arr is a constant (it's an array parameter not declared var or inout), therefore you cannot pass it by reference.
The obvious answer is that arr needs to be var or inout. Which one you need depends on what these functions are intended to do. What you have currently is discard the result of calls, which is pointless, so you are clearly not showing us what these functions are supposed to do.
#NakeCook's answer, simply make arr a var, makes it possible to pass it by reference, but it doesn't change the fact that the closure takes its argument by value (and the fact that sortFunc in testFunc is a pass-by-value function. That means testFunc gives an array to the function to sort, but does not care or want changes to be reflected back to it. If this is what you want, then that is the answer.
However, if testFunc is supposed to have an array, pass it to a sort function to sort, and wants to see changes to the array in its scope, then it needs to do something else:
func testFunc(sortFunc: (inout [Int]) -> ()) {
var x = [5,4,3,2,1]
sortFunc(&x)
}
testFunc { (inout arr: [Int]) -> () in
bubbleSort(&arr)
}
In this case, the closure's parameter is declared as inout (so it's passed by reference), and also the sortFunc (in testFunc)'s type explicitly mentions that it takes its parameter by reference.