Swift define and call inline closure directly - swift

I can assign an inline closure to a function type
> var a = { ()-> Bool in return true }
and use it:
> true==a()
$R2: Bool = true
if the function is a throw-away, it would be nice to use an inline directly. This doesn't work:
> true=={ ()-> Bool in return true }
error: repl.swift:16:5: error: binary operator '==' cannot be applied to operands of type 'Bool' and '() -> Bool'
According to the error, the RHS is the inline's function type, not its return type. Is there a different syntax I should use? Is it possible to call an inline directly?
Edit, after answer: This comes in very handy in cascaded conditions in if statements: if b==2, { /* do something only if b==2 passes*/}(), let x = ... { ...} else {...}

> true == a()
compares true with the result of calling the closure a (with an empty argument list). You can do the same inline, but you must still call the closure:
> true == { ()-> Bool in return true }()
$R0: Bool = true
Note that a test for equality with true is always redundant, so this expression is identical to
{ ()-> Bool in return true }()

Related

How can I make an instance conform to "Comparable"?

Did somebody have an idea how can I fix this?
In the following Line:
//Entry Image Shared
for shared in entryImagepostShared.sorted() {
postetImageShared.append(shared)
}
I get an Error Like: Referencing instance method sorted() on Sequence requires that Bool conform to Comparable
postetImages.removeAll()
postetImageComment.removeAll()
postetImageID.removeAll()
postetImageShared.removeAll()
for document in snapshot!.documents {
guard let entryImageURL = document["imageURL"] as? [String],
let entryImageComment = document["postText"] as? [String],
let entryImagepostShared = document["postShared"] as? [Bool] else { return }
//Entry Image URL's
for url in entryImageURL.sorted() {
postetImages.append(url)
}
let count = postetImageURL.count
imageURLCount += count
//Entry Image Comment
for comment in entryImageComment.sorted() {
postetImageComment.append(comment)
}
//Entry Image Shared
for shared in entryImagepostShared.sorted() {
postetImageShared.append(shared)
}
}
The Array's method sorted() requires that the array's values are comparable, i.e. there's a way to tell whether one value is less than another.
By default, the type Bool does not have this behavior.
If you need to sort an array of Bools, first you need to decide whether you want to see the false values first or the true values first.
Assuming the former, here are two ways to achieve this:
Use the sorted(by:) method which takes a closure. This closure takes two values and returns a Bool that indicates whether they are in increasing order:
let sorted = arrayOfBools.sorted { $0 == false || $1 == true }
Make the Bool conform to Comparable by implementing your own extension. Then you can just use sorted():
extension Bool: Comparable {
public static func < (lhs: Bool, rhs: Bool) -> Bool {
lhs == false || rhs == true
}
}
let sorted1 = arrayOfBools.sorted()

"Optional type '(() -> Bool)?' cannot be used as a boolean; test for '!= nil' instead" in delegate function call

My goal is to return a bool value of a function in a different class. The error is claiming the function is optional, but I don't understand how it's optional. I even tried to force unwrap it, but it gives me the error "'() -> Bool' is not convertible to 'Bool'".
I have my protocol in ManageCaptureVC file above the class declaration:
protocol ManageCaptureVCDelegate: class {
func selectedInterfaceOrientationIsLandscape() -> Bool
}
My defined delegate in my ManageCapture class:
weak var delegate: ManageCaptureVCDelegate?
And my if statement to try to check the bool value:
if self.delegate?.selectedInterfaceOrientationIsLandscape {
/*code*/
}
The original function in the delegate class is:
func selectedInterfaceOrientationIsLandscape() -> Bool {
if(selectedInterfaceOrientation == interfaceOrientations.landscapeLeft ||
selectedInterfaceOrientation == interfaceOrientations.landscapeRight){
return true
}
return false
}
You need to call the function, not reference the function.
Change:
if self.delegate?.selectedInterfaceOrientationIsLandscape {
to:
if self.delegate?.selectedInterfaceOrientationIsLandscape() {
But since you are using optional chaining, it should be:
if self.delegate?.selectedInterfaceOrientationIsLandscape() ?? false {

Swift closure omission example?

When I read the Swift documentation provided by Apple, I found some concept not clear for me...
When a closure’s type is already known, such as the callback for a delegate, you can omit the type of its parameters, its return type, or both. Single statement closures implicitly return the value of their only statement.
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
What does it means the callback for a delegate? Could you give me an example? If both are omitted, should we need the in keyword?
There is nothing simpler. In this case the meaning of delegate is that the closure is used as a variable. Consider the following example:
class Downloader {
var onDownloaded: ((Data) -> Void)?
func startDownloading() {
...
}
}
Used as:
let downloader = Downloader()
downloader.onDownloaded = { data in
print("Downloaded: \(data.count) B")
}
downloader.startDownloading()
As you can see, I did not specify neither the type or the return value in the closure, because the left side of the expression (.onDownloaded =) provides them.
The same applies for method parameters:
func startDownloading(onDownloaded: ((Data) -> Void)?) {
...
}
However, we still need in in the closure. The keyword separates the parameter names from the closure body. Of course, we could make the parameters anonymous:
downloader.onDownloaded = {
print("Downloaded: \($0.count) B")
}
It states that the parameter type can be inferred from the delegate. A delegate is a protocol, which is where you define the types of the method parameters. This means that when implementing the delegate method, the compiler already knows about the method types through the declared protocol.
An example:
let sortedAnimals = animals.sort { (one: String, two: String) -> Bool in
return one < two
}
The first simplification is related to the parameters. The type inference system can calculate the type of the parameters in the closure:
let sortedAnimals = animals.sort { (one, two) -> Bool in return one < two }
The return type can also be inferred:
let sortedAnimals = animals.sort { (one, two) in return one < two }
The $i notation can substitute the parameter names:
let sortedAnimals = animals.sort { return $0 < $1 }
In single statement closures, the return keyword can be omitted:
let sortedAnimals = animals.sort { $0 < $1 }
For strings, there's a comparison function which makes string comparison even shorter:
let sortedAnimals = animals.sort(<)
Each step outputs the same result and it is for you to decide what is concise, but readable at the same time.

Null-coalescing assignment operator in Swift 3

I'm trying to create a null-coalescing assignment operator in Swift 3. In other words, instead of this:
x = x ?? y
I want this:
x ??= y
Swift 3 does not seem to like my operator. Here's its definition:
infix operator ??= : AssignmentPrecedence
func ??=(lhs: inout Any?, rhs: #autoclosure () -> Any?) {
if lhs != nil { return }
lhs = rhs()
}
var x = 3
x ??= 7 // Cannot convert value of type 'Int' to expected argument type 'inout Any?'.
I've done it without the #autoclosure too. My understanding is that the precedence group AssignmentPrecedence already contains the assignment declaration, so this is unlikely to be the problem.
How can I do this in Swift 3?
First, make the operator generic instead of using Any:
infix operator ??= : AssignmentPrecedence
func ??=<T>(lhs: inout T?, rhs: #autoclosure () -> T?) {
if lhs != nil { return }
lhs = rhs()
}
Second, the left operand needs to be an optional (otherwise it
could not be tested against nil):
var x: Int? = 3
x ??= 7
I came up with my own 'flavor' of a null-coalescing assignment operator, similar to the above, but by adding a return type, you can both do assignment and return at the same time which is more in line with normal '??' behavior, with the addition of the assignment from the RHS to the LHS if LHS is null. It's perfect for resettable lazy vars. Here's my version...
// Null-coalescing assignment operator
infix operator ??= : AssignmentPrecedence
#discardableResult
func ??= <T>(lhs:inout T?, rhs:#autoclosure () -> T) -> T {
if let lhs = lhs {
return lhs
}
let rhsResult = rhs()
lhs = rhsResult
return rhsResult
}
With the above, I can now do resettable lazy vars like this...
private var qCache:Int?
var q:Int {
return qCache ??= {
print("Lazy-calculating q...")
return 44
}()
}
func resetQ() { qCache = nil }
print("1: q is \(q)")
print("2: q is \(q)")
print("3: q is \(q)")
print("Resetting lazy q...")
resetQ()
print("4: q is \(q)")
Output...
Lazy-calculating q...
1: q is 44
2: q is 44
3: q is 44
Resetting lazy q...
Lazy-calculating q...
4: q is 44
You can also implement the setter too, if you wish as well as separating out the 'lazy calc' function...
func lazyCalcQ() -> Int {
print("Lazy-calculating q...")
return 44
}
private var qCache:Int?
var q:Int {
get { return qCache ??= lazyCalcQ() }
set { qCache = newValue }
}
func resetQ() { qCache = nil }
Going a step further, you can use implicitly-unwrapped datatypes so you can use the assignment of nil to be the reset, yet you are always guaranteed a value from the getter. The only down-side is you still sometimes have to force-unwrap it to silence some warnings like in the print statements below, but again, you are guaranteed a value, so it's safe to do.
Note: Personally I prefer the approach above with the non-implicitly-unwrapped version and the extra 'reset' function--especially if it's a read-only property--because it makes the API much clearer, but I'm sharing this for completeness since it shows a creative use for nil-as-reset.
func lazyCalcR() -> Int {
print("Lazy-calculating r (i.e. the default when reset with 'nil')...")
return 10
}
private var rCache:Int?
var r:Int! {
get { return rCache ??= lazyCalcR() }
set { rCache = newValue }
}
print("1: r is \(r!)")
r += 10
print("2: r is \(r!)")
r += 10
print("3: r is \(r!)")
print("Resetting r to default...")
r = nil
print("4: r is \(r!)")
Output...
Lazy-calculating r (i.e. the default when reset with 'nil')...
1: r is 10
2: r is 20
3: r is 30
Resetting r to default...
Lazy-calculating r (i.e. the default when reset with 'nil')...
4: r is 10
Of course the above are all trivial examples using an int, but I use it to do things like calculating complex paths based on bounds, etc.
My next attempt will be to hide all of this in property wrappers, eliminating the need for this operator itself.

Swift closure capture and inout variables

Consider the following code:
func foo(inout success: Bool) -> (()->()) {
return { _ in
success = true
print (success)
}
}
var success = false
let closure = foo(&success)
closure() //prints "true"
print(success) //prints "false"
The closure appears to be creating a copy of success and does not change the original. Why is this taking place? I had assumed that the closure would point to the original because we are passing an inout variable.
It makes sense that this wouldn't update your success variable because your inout parameter is a parameter of foo, not of the closure itself. You get the desired behavior if you make the inout parameter a parameter of the closure:
var success = false
let closure = { (inout flag: Bool) -> () in
flag = true
print(flag)
}
closure(&success) //prints "true"
print(success) //prints "true"
This pattern also works with the function, too, as long as you keep the inout parameter a parameter of the closure:
func foo() -> ((inout Bool)->()) {
return { flag in
flag = true
print (flag)
}
}
var success = false
let closure = foo()
closure(&success) //prints "true"
print(success) //prints "true"
You also get the desired behavior if you use a reference type:
class BooleanClass: CustomStringConvertible {
var value: Bool
init(value: Bool) {
self.value = value
}
var description: String { return "\(value)" }
}
func foo(flag: BooleanClass) -> (()->()) {
return {
flag.value = true
print (flag)
}
}
let success = BooleanClass(value: false)
let closure = foo(success)
closure() //prints "true"
print(success) //prints "true"
This seems to be covered by Swift Evolution proposal 0035, and is considered a bug.
The document there refers to the inout parameter to the function as "a shadow copy that is written back to the argument when the callee returns". This seems to mean that there is, in essence, a temporary variable named success in the executing context of foo(). The value of that temp is then put into the outer success only when foo() returns.
Since in your foo(), the closure has not run when foo() returns, the value of the "shadow copy" has not changed. The outer success keeps its value.
The important part is that the closure has captured the shadow copy, not the outer success as you expect. So when the closure finally runs, that variable's value does change, but it no longer has any connection to the original outer success.
The proposal uses this snippet to demonstrate:
func captureAndEscape(inout x: Int) -> () -> Void {
let closure = { x += 1 }
closure()
return closure
}
var x = 22
let closure = captureAndEscape(&x)
print(x) // => 23
closure()
print("still \(x)") // => still 23