'Int' is not identical to 'UInt8' in closure - swift

I am trying to create a closure that keeps a reference to the local variable of the outer function and I keep getting this ambigious error int is not identical to unint8. It does not make sense to me because there no arrays involved here. There are also no UInt8s involved here too.
func increment(n:Int)-> ()->Int {
var i = 0
var incrementByN = {
() -> Int in
i += n
}
return incrementByN
}
var inner = increment(4)
inner()
inner()
inner()
I found that I can fix this by returning i after i+=n. I thought that i+=n would return on it's own but apparently it does not.

+= for (Int, Int) is declared as
func +=(inout lhs: Int, rhs: Int)
It returns nothing.
I don't know why UInt8 involves, though.
Maybe, it's because func +=(inout lhs: UInt8, rhs: UInt8) is the last one of func +=(...) declarations.

Not sure what the UInt8 is about, but it seems that += does not have a value.
var i = 1;
let x = i += 3; // now x is of type ()
You can explicitly return the new value of i:
var incrementByN = {
() -> Int in
i += n
return i
}

Related

Using #discardableResult for Closures in Swift

Swift 3 has introduced the #discardableResult annotation for functions to disable the warnings for an unused function return value.
I'm looking for a way to silence this warning for closures.
Currently, my code looks like this:
func f(x: Int) -> Int -> Int {
func g(_ y: Int) -> Int {
doSomething(with: x, and: y)
return x*y
}
return g
}
In various places I call f once to obtain a closure g which I then call repeatedly:
let g = f(5)
g(3)
g(7)
g(11)
In most places I'm only interested in the side effects of the nested call to doSomething, and not in the return value of the closure g. With Swift 3, there are now dozens of warnings in my project for the unused result. Is there a way to suppress the warnings besides changing the calls to g to _ = g(...) everywhere? I couldn't find a place where I could place the #discardableResult annotation.
I don't think there's a way to apply that attribute to a closure. You could capture your closure in another that discards the result:
func discardingResult<T, U>(_ f: #escaping (T) -> U) -> (T) -> Void {
return { x in _ = f(x) }
}
let g = f(5)
g(3) // warns
let h = discardingResult(g)
h(4) // doesn't warn
I was looking for an answer to this recently, and I've found another way (a newer way) to do this!
It could arguably be overkill for some simple problems, but I just thought that this is an interesting yet neat approach that's worth sharing.
Say you have a closure that doubles an integer value:
let double = { (int: Int) -> Int in
return int * 2
}
With Swift 5.0 (SE-0216) introducing the #dynamicCallable attribute, you can "wrap" your closure with #discardableResult by creating a dynamically callable class or struct as such:
// same for struct, except without the need of an initializer
#dynamicCallable
class DiscardableResultClosure<T, U> {
var closure: (T) -> U
#discardableResult
func dynamicallyCall(withArguments args: [Any]) -> U {
let arg = args.first as! T
return self.closure(arg)
}
// implicit for struct
init(closure: #escaping (T) -> U) {
self.closure = closure
}
}
double(5) // warning: result of call to function returning 'Int' is unused
let discardableDouble = DiscardableResultClosure(closure: double)
discardableDouble(5) // * no warning *
Even better, in Swift 5.2 (SE-0253), you can create a dynamically callable struct using a built-in callAsFunction method without going through the trouble of using the attribute #dynamicCallable (or using class) with its sometimes cumbersome declaration.
struct DiscardableResultClosure<T, U> {
var closure: (T) -> U
#discardableResult
func callAsFunction(_ arg: T) -> U {
return closure(arg)
}
}
let discardableDouble = DiscardableResultClosure(closure: double)
discardableDouble(5) // * no warning *

Function with generic type

I have a function that can calculate the sum of numbers in array with condition like so:
func sumOfArrayWithCondition(array: [Int], filter: (element: Int) -> Bool) -> Int {
var result = 0
for i in 0..<array.count where filter(element: array[i]) {
result += array[i]
}
return result
}
Now I want it to work with Int, Float, Double type. I have tried, but didn't work.
protocol Addable {
func +(lhs: Self, rhs: Self) -> Self
}
extension Int: Addable {}
extension Double: Addable {}
extension Float: Addable {}
func sumOfArrayWithCondition<T: Addable>(array: [T], filter: (element: T) -> Bool) -> T {
var result = 0
for i in 0..<array.count where filter(element: array[i]) {
result += array[i] // <-------- Error here
}
return result // <-------- Error here
}
But it says:
Binary operator '+=' cannot be applied to operands of type 'Int' and 'T'
So how to do it.
Any helps would be appreciated. Thanks.
First issue is that the compiler is inferring the type Int for the var result because you don't declare a type and initialize it with 0. But you need result to be of type T.
First, in order to initialize result as an instance of type T with the value 0, you need to specify that Addable is also IntegerLiteralConvertible, which is already true for Int, Double and Float. Then you can declare result as type T and go from there.
As Rob pointed out, you also need to add the += function to your protocol if you want to be able to use it.
So the final code that achieves what you are looking for is:
protocol Addable : IntegerLiteralConvertible {
func +(lhs: Self, rhs: Self) -> Self
func +=(inout lhs: Self, rhs: Self)
}
extension Int: Addable {}
extension Double: Addable {}
extension Float: Addable {}
func sumOfArrayWithCondition<T: Addable>(array: [T], filter: (element: T) -> Bool) -> T {
var result:T = 0
for i in 0..<array.count where filter(element: array[i]) {
result += array[i]
}
return result
}
As Rob said, result is an Int. But there's no need to create that method at all. You're wanting to call that like so, based on your method signature:
let sum = sumOfArrayWithCondition(myArray, filter: myFilter)
instead, all you have to do is use existing methods provided by swift:
let sum = myArray.filter(myFilter).reduce(0) { $0 + $1 }

Im confused on how this function is being called, there is no call for it?

I'm confused on how getFunctionNeededForReference is running. There is no call for it and where are the functions returned to? where are they going? I know they are being referenced but where are the functions going to, there is not call for getFunctionNeededForReference in the beginning? there is no call sending the argument flag anyway?
func add ( a: Int , b : Int)-> Int {
//returing a result and not a variable
return a + b
}
func multiply ( a: Int, b: Int) -> Int{
return a * b
}
// declaring a function as a variable, it takes in 2 Ints and returns an Int
var f1 : (Int, Int)-> Int
f1 = add
f1 = multiply
// Function as a parameter
func arrayOperation (f: (Int, Int) -> Int , arr1: [Int] , arr2: [Int]) -> [Int]
{
// Declaring and initializing an empty array to return
var returningArray = [Int]()
for (i, val) in enumerate(arr1)
{
returningArray.append(f(arr1 [i], arr2 [i]))
}
return returningArray
}
arrayOperation(add, [2,3,4], [4,5,6])
arrayOperation(multiply, [2,3,4], [4,5,6])
//Function as a return value
func getFunctionNeededForReference (flag : Int) -> (Int,Int) ->Int
{
if flag == 0 {
return add
}else {
return multiply
}
}
What you've posted is just some example code showing things that Swift supports. It's not code that's useful for anything. It's just demonstrating Swift's syntax for first-class functions.
If you don't understand what “first-class functions” means, you can look up the term in your favorite search engine and find many explanations.

Strange behavior with swift compiler

I have the following function in swift:
func f() -> Int
{
let a = String("a")
let b = a.unicodeScalars
println(b[b.startIndex].value)
//return b[b.startIndex].value
return 1
}
If I uncomment the first return statement and comment the second one, then I get the compiler error:
Could not find the member 'value'
Why this happens even when I have access to this member in the println function call?
EDIT:
In order to make the question more clear, consider the following code:
struct point {
var x: UInt32
var y: UInt32
init (x: UInt32, y: UInt32) {
self.x = x
self.y = y
}
}
func f () -> Int {
var arr = [point(x: 0, y: 0)]
return arr[0].x
}
In this case, the compiler error is:
UInt32 is not convertible to Int
My question is: Why the compiler errors are different even when the problem is the same in both cases?
value returns a UInt32. Cast it to an Int.
return Int(b[b.startIndex].value)
Alternatively, you could have the function return a UInt32 as #GoodbyeStackOverflow mentions.
func f() -> UInt32
Return this instead:
return Int(b[b.startIndex].value)
The issue is that b[...].value returns a UInt32, which starting Swift 1.2 no longer converts to Int.

Swift: why 'subscript(var digitIndex: Int) -> Int' is a valid function signature?

This piece of code comes from Swift documentation https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html
extension Int {
subscript(var digitIndex: Int) -> Int {
var decimalBase = 1
while digitIndex > 0 {
decimalBase *= 10
--digitIndex
}
return (self / decimalBase) % 10
}
}
Apparently var is a reserved word, so why it is legal to declare: subscript(var digitIndex: Int) -> Int?
If I change the signature to subscript(#digitIndex: Int) -> Int, I will get this compiler error:
My questions are:
1) why the signature is valid?
2) why my change causes an exception?
Declaring a function argument with var means that it can be modified, is not a constant. In your case, without using var, you had a constant argument but you attempted to decrement it. Thus the error.
Your two cases are:
func foo (x: int) { /* x is a constant, like `let x: int` */ }
func foo (var x: int) { /* x is not a constant */ }