What is the usecase for ignored parameters in Swift - swift

In Swift, you can write the following:
func foo(_:Int) -> { return 1 }
Where the underscore is an ignored parameter. I only know this because of the documentation, but cannot think of ANY usecase on why you would even do this. Am I missing something?

Ignoring parameters (or members of a tuple, which are pretty close to the same thing) makes sense when:
You're overriding a superclass function or implementing a function defined by a protocol, but your implementation of that function doesn't need one of the parameters. For example, if you hook app launching but don't need a reference to the shared UIApplication instance in that method:
override func application(_: UIApplication!, didFinishLaunchingWithOptions _: NSDictionary!) -> Bool { /* ... */ }
You're providing a closure (aka block in ObjC) as a parameter to some API, but your use of that API doesn't care about one of the parameters to the closure. For example, if you're submitting changes to the Photos library and want to throw caution to the wind, you can ignore the success and error parameters in the completion handler:
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
// change requests
}, completionHandler: { _, _ in
NSLog("Changes complete. Did they succeed? Who knows!")
})
You're calling a function/method that provides multiple return values, but don't care about one of them. For example, assuming a hypothetical NSColor method that returned components as a tuple, you could ignore alpha:
let (r, g, b, _) = color.getComponents()
The reasoning behind this is that it makes your code more readable. If you declare a local name for a parameter (or tuple member) that you don't end up using, someone else reading your code (who could well be just the several-months-later version of yourself) might see that name and wonder where or how it gets used in the function body. If you declare upfront that you're ignoring that parameter (or tuple member), it makes it clear that there's no need to worry about it in that scope. (In theory, this could also provide an optimization hint to the complier, which might make your code run faster, too.)

Perhaps you're overriding a method and your override ignores one of the parameters? Making it clear that you're ignoring the parameter saves future coders from having to look through your code to work out that it's not using the parameter and makes it clear that this was intentional. Or maybe it's to create some sort of Adapter pattern where you make it clear that one of the parameters is being ignored.

Related

how to extend optional chaining for all types

If we have optional values foo and bar, Swift will allow us to write:
foo?.doSomething(bar)
Which will evaluate to nil if foo is nil. But it will not let us write:
foo?.doSomething(bar?)
That is, optional chaining only works on the arguments outside a function call, not inside the argument list. (The reasons for this limitation are unclear, but here we are.)
Suppose I want to write an apply function that lets me move things into the jurisidiction of optional chaining, like so:
bar?.apply { foo?.doSomething($0) }
Here, apply is a generic function that takes one argument (in this case bar) and then executes the closure. So if either foo or bar is nil, the expression will be nil.
Here's what I’ve tried:
public protocol HasApply {}
extension HasApply {
public func apply<T>(_ f : (Self) -> T) -> T {
f(self)
}
}
That’s fine as far as it goes. But to make it work, I still have to explicitly apply the protocol to the types I care about:
extension Int : HasApply {}
OK, that makes it work with Int. But I don’t want to copy & paste for every type. So I try this:
extension AnyObject : HasApply {}
No, that won’t work: the error is Non-nominal type 'AnyObject' cannot be extended.
Hence the question: is there no way to make this generic function work as a protocol method?
is there no way to make this generic function work as a protocol method?
No, you must "explicitly apply the protocol to the types I care about".
However, you are in fact reinventing the wheel. This is the use case of flatMap/map. If both foo and bar are optional, you can write:
bar.flatMap { foo?.doSomething($0) }
Note the lack of ? after bar. You are calling flatMap on Optional, rather than bar's type. If doSomething returns T, the above expression will return T?.
If only bar is optional, use map:
bar.map { foo.doSomething($0) }
As Sweeper pointed out, the language already provides you the tool for this, in the form of the map/flatMap functions.
But you could also write
if let foo = foo, let bar = bar {
foo.doSomething(bar)
}
This is an easier to read, understand, and maintain code, with clearly transmits the intent: you want doSomething to be called if both the receiver of the call and its argument are non-nil.
Now, why it would not be a good idea for the language to have this feature built-in - it's due to the way the compiler processes the code: from left to right.
The optional chaining is a short-circuit operator, thus
foo?.someExpensiveComputation().doSomething(bar)
will stop at runtime as soon as it detects that foo is nil. Which means that someExpensiveComputation will not be executed. Not the same thing can be said about a construct like this:
foo?.someExpensiveComputation().doSomething(bar?)
Assuming foo is not nil, but bar is nil, the program will execute someExpensiveComputation just to find out that doSomething doesn't need execution. Thus, the short-circuit no longer applies.
Let's take another example, let's assume doSomething has two parameters:
foo?.doSomething(someExpensiveComputation(), bar)
Again, the compiler evaluates from left to right, thus the expensive computation will be performed, just to be thrown away once the program detects at runtime that the second argument is nil.
Now, yes, the compiler might implement some advanced heuristics of looking ahead for possible nil values, but this would be highly complicated and would add lots of performance penalties at runtime.
The bottom line, the compiler will provide you with short-circuits, as long as those are well-behaved, predictable, and don't overwhelm the compiler.

Why does the generic type not participate in method overloading via constraint further down the call chain?

Swift allows generic methods to be overloaded by the constraints placed upon the generic types passed in. If you use this with concrete types, then the type passed in will participate in this overloading and constraints will be inferred from that type.
As soon as a generic method delegates to another with overload resolution, the constraints can no longer be inferred and will instead utilize the constraints already placed on the type from above.
protocol Conformance {}
extension String : Conformance {}
// #1
func baseMethod<T>(_ value: T) {
let isConforming = T.self is Conformance.Type
}
// #2
func baseMethod<T>(_ value: T) where T : Conformance {
let isConforming = T.self is Conformance.Type
}
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
func run() {
// Calls #2, isConforming = true
baseMethod(String())
// Calls #1, isConforming = true
delegatingMethod(String())
}
I assume this is there so that you have sufficient type information from the call site about what constraints are applicable no matter where the generic type is used, but it seems to severely and artificially limit the utility of overloading by constraint.
Are there any known workarounds to this oddity? Something that emulates this would be extremely useful.
Swift allows generic methods to be overloaded by the constraints placed upon the generic types passed in.
Yes...but be very clear that this is a static overload, not a dynamic override. It is based on types that can be proven at compile-time.
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
We're compiling this now, and we need to write it as a concrete, static function call, possibly inlined, into the binary. What do we know about T? We know nothing about T, so any where clause will fail.
We don't even know about how this function is called, because the call may come from another compile unit or module. While in principle, it could have different semantics based on access level, such that one version were used when it is private and all calls can be evaluated, and another used when it's public, that would be a really horrible source of bugs.
What you're asking for is that delegatingMethod defer its decision about what function call to make until runtime. That's not how generics work. Moreover, you're asking that all the where clauses be encoded somewhere in the binary so that they can be evaluated at runtime. Also not how generics work. That would require a much more dynamic dispatch system than Swift wants to implement. It's not impossible; it's just a completely different animal, and prevents lots of optimizations.
This feels like you're trying to reinvent class inheritance with protocols and generics. You can't. They're different solutions and have different features. Class inheritance is fundamentally dynamic. Protocols and generics are fundamentally static. If you want dynamic dispatch based on specific types, use classes.

When to use delegate, inout or completion in Swift?

When we call some code and need a response with multiple parameters we have multiple options in Swift:
Completion block
Delegate
Inout parameters
Wrapper object (simply put all parameters inside an object)
I was wondering if there were some good guidelines to when to use what? Specifically when would it be a bad practise to use inout instead of delegate?
To be VERY specific:
Also an example that can be used to explain:
I have class A that communicates with class B. Class A needs a list of data AND an optional error.
So right now I'm leaning towards using inouts:
Class A:
var error = ServiceError()
let wordSuggestions = B.parseSuggestionResponse(json: result as! NSDictionary, error: &error)
if error.type == .none {
// Success, now use wordSuggestions for something!
} else {
self.handleError(error: error)
}
Is there some disadvantages for this approach vs using delegates?
I will explain when each method should be used.
A completion block is used when the operation takes time. For example, UIView.animate has a completion block parameter because animating views take time.
A delegate is used only when some of object is present especially when that object can have multiple states. This is widely used for communication between the view and the controller When there is only a method, delegates don't work. For example, a GADInterstitial has a delegate because it can have different states, such as the user dismissing the ad, user clicks the ad and leaves the app, the ad is loaded etc.
Inout parameters are mainly used for passing value types as references. I can't find any usage of this in the iOS SDK because there is no inout in Objective-C. The closest thing to it is UnsafeMutablePointer<T>. Basically, if you want to make a method that takes a bunch of value type arguments and you want to change their value, use inout! Refer to this page for more info.
From my own experience, wrapper objects are rarely used in swift. That is because we have tuples! You can wrap everything in a tuple and pass that around. I don't usually create a new struct or class just to wrap a few parameters. But do use them if your data structure becomes something complicated like [(String, [String: (String, Int)])].

I can't figure out how this switch statement is working?

func performMathAverage (mathFunc: String) -> ([Int]) -> Double {
switch mathFunc {
case "mean":
return mean
case "median":
return median
default:
return mode
}
}
I got this example from a swift learning book and its speaking of the topic of returning function types and this is just a part of the whole program I didn't want to copy and paste it all. My confusion is that the book says:
"Notice in performMathAverage , inside the switch cases, we return
either mean , median , or mode , and not mean() , median() , or mode()
. This is because we are not calling the methods, rather we are
returning a reference to it, much like function pointers in C. When
the function is actually called to get a value you add the parentheses
suffixed to the function name. Notice, too, that any of the average
functions could be called independently without the use of the
performMathAverage function. This is because mean , median , and mode
are called global functions ."
The main question is: "Why are we not calling the methods?"
and what do they mean we are returning a reference to it??
What do they mean by reference? Im just confused on this part.
You stated your main question as:
"Why are we not calling the methods?" and what do they mean we are returning a reference to it??
This is a little tricky to grasp at first, but what it's saying is that we don't want the result of the function, we want the function itself.
Sometimes things like this are easier to understand w/ a type alias:
Starting w/ [Int] -> Int, what we're saying there is "a function that takes an array of Ints and returns a single Int"
Let's make a type alias for clarity:
typealias AverageFunction = [Int] -> Int
Now our function (from your example) looks like this:
func performMathAverage(mathFunc: String) -> AverageFunction {
Although, the naming conventions here are pretty confusing since we're not performing anything, instead let's call it like this:
func getAverageFunctionWithIdentifier(identifier: String) -> AverageFunction {
Now it's very clear that this method is functioning like a factory that returns us an average function based on the identifier we provide. Now let's look at the implementation:
func getAverageFunctionWithIdentifier(identifier: String) -> AverageFunction {
switch identifier {
case "mean":
return mean
case "median":
return median
default:
return mode
}
}
So now, we're running a switch on the identifier to find the corresponding function. Again, we're not calling the function because we don't want the value, we want the function itself. Let's look at how we would call this:
let averageFunction = getAverageFunctionWithIdentifier("mean")
Now, averageFunction is a reference to the mean function which means we can use it to get the mean on an array of integers:
let mean = averageFunction([1,2,3,4,5])
But what if we wanted to use a different type of average, say median? We wouldn't have to change anything except for the identifier:
let averageFunction = getAverageFunctionWithIdentifier("median")
let median = averageFunction([1,2,3,4,5])
This example is pretty contrived, but the benefits of this is that by abstracting a function out to it's type (in this case [Int] -> Int, we can use any function that conforms to that type interchangeably.
This is functional programming!
This has to do with the functional programming aspects of swift. Here functions are treated like first class citizens meaning you can treat them like variables.
Why are we not calling the methods?
You are not calling the methods, because you have no argument to apply. The point of the function is to determine which function you would like to use. Of course the name of the function is terrible and does not accurately represent what the function does. It should be more like func determineMathFuncToUse, then you could use it like
var myFunc = determineMathFuncToUse("median")
// Now, you would be able to use myFunc just like you would use median
// e.g. myFunc(some_array) == median(some_array)
This is pretty easy to understand. In Swift you can store references to functions (the closest you can achieve in Objective-C is the reference to block).
func performMathAverage (mathFunc: String) -> ([Int]) -> Double
This is the function whose return type is:
([Int]) -> Double
As you can see the return type of this function is a function which accepts an array of Int and returns Double.
And in code you see that it returns one of three functions: mean, mode, and median. Each of these functions accepts an array of Int and returns Double.
Due to this code below:
let meanFunc = performMathAverage("mean")
let mean = meanFunc(someIntArray)
is identical to:
let mean = mean(someIntArray)
I hope this helps.
The reason why functions are NOT executed in code is because this example illustrates how you can STORE reference to functions.
It might be difficult to understand why you would want to do it in this particular case, but, hey, printing "Hello world" also seems meaningless :)
You are referring to an example in a tutorial so it is not strange that they are oversimplifying things. However, believe me, that in a real world there are many cases in which storing references to functions is very-very useful!
One obvious example is when you want to store reference to some completion handler which you want to execute at the end of some lengthy operation. And which can be different depending on the context from which you initiated this operation.
To answer your question, you are effectively returning the function itself, and not the result of calling that function. In this case, it lets you choose a function (using the switch statement) and evaluate it later. A helpful way to think about it is that functions are also a type of variable, and you can pass them around as well as evaluate them.
As a general stylistic thing, it's good practice to end each case with a break. It makes no difference here because return will also end the execution of the function, but without a break, all code after the correct case will be executed, not just the code within the correct case. Running into another case statement doesn't break out of the switch statement by itself.
Why are we not calling the methods?
Presumably, the method will be called later. The purpose of the switch statement is to return a function that can be used later.
What do they mean we are returning a reference to it? ... What do they mean by reference?
The "reference" language is a bit confusing - functions are reference types, but that isn't super important to what is going on. You can think of it as just returning a function.
The bottom line is that functions in swift can be used like any other type - they can be stored in variable or constants, they can be passed into a function as a parameter, and they can be returned from a function.
In this case, you have a function that is designed to return a function. If you want to obtain the mean, you pass the string "mean" and the function will return a new function that will obtain the mean when you call it.

Create and run a Selector with several parameters for class functions

I have a situation where I use a class to do a number of conversions with a large number of rules which have the general form of:
private class func rule0(inout account: String, _ version: Int) -> String? {
return nil; // Use default rule.
}
The function names just increase the rule number: rule1, rule2 etc...
I get the rule number from an external source and now want to find a generic way to call the right rule function depending on the given rule number. I could use a big switch statement, but I'm more interested in generating a selector from a string and call that.
My attempts led me to:
let ruleFunction = Selector("rule\(rule):_:");
let result = ruleFunction(&account, version);
but that only causes this error on the second line:
'(inout String, #lvalue Int) -> $T4' is not identical to 'Selector'
What is the right way to accomplish that? And btw, what means "$T4"? That error message is hard to understand, to say it friendly.
Additional note: I'm aware of approaches using a timer or detouring to Obj-C, but am rather interested in a direct and pure Swift solution. How is the Selector class to be used? Can it be used to directly call what it stands for? How do classes like NSTimer use it (detour to Obj-C?)?
A couple of approaches that don't use Selector. If all of the "rules" have the same signature, then you could either put them in an array, with the index of the function in the array indicating the rule number, like this:
let functionArray = [rule0, rule1, rule2, rule3] // etc...
Then, when it is time to call the function, you just access the one you want with a subscript:
let result = functionArray[ruleNumber](account, version)
You could do the same thing with a dictionary that looked something like this:
let functionDict = ["rule0": rule0, "rule1": rule1] // etc...
And then get the function using the string value that you create when you get the rule number from your external source:
let result = functionDict["rule\(ruleNumber)"]?(account, version)
The dictionary approach would work better if you weren't able to guarantee that rule0 would always be at index 0 in the array.
A caution, though: I have tried this and I've been able to get it to work without the inout keyword, but not with it. I don't know if it is a bug, or what, but Swift doesn't seem to want to let me create arrays or dictionaries of functions that take inout parameters.
If you absolutely require the inout parameter for your function to work, then my suggestion won't help. If there is a way to do what you want without the inout, then this might be the solution for you.