What is the practical use of nested functions in swift? [duplicate] - swift

This question already has answers here:
What is the benefit of nesting functions (in general/in Swift)
(3 answers)
Closed 6 years ago.
What is the practical use of nested functions? It only makes the code harder to read and doesn't make a particular case easy.
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backwards ? stepBackward : stepForward
}
Source

I think the core of your question is: Why not use private function instead of an ugly nested function?
Simply put, nested functions can ease readability and encapsulation.
Similarly one can ask, what's the practical use of local variables (of a function) vs instance variables? To me it's really the same question. Only that nested functions are less common.
Readability
A private function can still be accessed from other functions in your class. The same isn't true for nested functions. You're telling your developers, this only belongs to this function (contrary to private functions where they belong to the entire class). Back off and don't mess with it, if you need similar capability, go write your own!
The moment you see a private function you have to think, which function will call it. Is it the first function or the last? Let me search for it. Yet with a nested function you don't have to look up and down. It's already known which function will call it.
Also if you have 5 private functions, where 3 of them are called in a single public function then by nesting them all under the same public function you're communicating to other developers that these private functions are related.
In short, just as you don't want to pollute your public namespace, you don't want to pollute your private namespace.
Encapsulation
Another convenience is that it can access all the local parameters to its parent function. You no longer need to pass them around. This would eventually mean one less function to test, because you've wrapped one function inside another. Additionally if you're calling that function in a block of the non-nested function, then you don't have to wrap it into self or think about creating leaks. It's because the lifecycle of the nested function is tied to the lifecycle of its containing function.
Another use case would be when you have very similar functions in your class, say like you have:
extractAllHebrewNames() // right to left language
extractAllAmericanNames() // left to right language
extractAllJapaneseNames() // top to bottom language
Now if you have a private func named printName (that prints names), it would work if you switch the case based on language, but what if just you don't/can't do that. Instead you can write your own nested functions (They could all now have the exact same name. because each is in a different namespace.) inside each separate extract function and print the names.
Your question is somewhat similar, to why not use 'if else' instead of a 'Switch case.
I think it's just a convenience provided (for something that can be dealt without using nested functions).
NOTE: A nested function should be written before it's callsite within the function.
Error: use of local variable 'nested' before its declaration
func doSomething(){
nested()
func nested(){
}
}
No Error:
func doSomething(){
func nested(){
}
nested()
}
Similarly a local variable used in a nested function must be declared before the nested function
BE AWARE:
If you're using nested functions, then the compiler won't enforce self checks.
The compiler is not smart enough. It will NOT throw error of:
Call to method 'doZ' in closure requires explicit 'self.' to make capture semantics explicit
This could result in hard to find memory leaks. e.g.
class P {
var name: String
init(name: String) {
print("p was allocated")
self.name = name
}
func weaklyNested() {
weak var _self = self
func doX() {
print("nested:", _self?.name as Any)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
doX()
}
}
func stronglyNested() {
func doZ() {
print("nested:", name)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
doZ() // will NOT throw error of: `Call to method 'doZ' in closure requires explicit 'self.' to make capture semantics explicit`
}
}
deinit {
print("class P was deinitialized")
}
}
class H {
var p: P
init(p: P) {
self.p = p
}
}
var h1: H? = H(p: P(name: "john"))
h1?.p.weaklyNested()
h1 = nil // will deallocate immediately, then print nil after 2 seconds
var h2: H? = H(p: P(name: "john"))
h2?.p.stronglyNested()
h2 = nil // will NOT deallocate immediately, will print "john" after 2 seconds, then deallocates
tl;dr solution:
use weak var _self = self and inside the nested function reference to self with the weak reference.
don't use nested functions at all :( Or don't use instance variables inside your nested functions.
This part was written thanks to this original post from Is self captured within a nested function?

One use case is operations on recursive data structures.
Consider, for instance, this code for searching in binary search trees:
func get(_ key: Key) -> Value? {
func recursiveGet(cur: Node) -> Value? {
if cur.key == key {
return cur.val
} else if key < cur.key {
return cur.left != nil ? recursiveGet(cur: cur.left!) : nil
} else {
return cur.right != nil ? recursiveGet(cur: cur.right!) : nil
}
}
if let root = self.root {
return recursiveGet(cur: root)
} else {
return nil
}
}
Of course, you can transform the recursion into a loop, doing away with the nested function. I find recursive code often clearer than iterative variants, though. (Trade off vs. runtime cost!)
You could also define recursiveGet as (private) member outside of get but that would be bad design (unless recursiveGet is used in multiple methods).

There is the principle (since Objective-C) that "code can be data". You can pass code around, store it in a variable, combine it with other code. This is an extremely powerful tool. Frankly, if I didn't have the ability to treat code as data, most of the code I write would be ten times harder to write, and ten times harder to read.
Functions in Swift are just closures, so nested functions make perfectly sense, since this is how you write a closure when you don't want to use one of the many available shortcuts.

In your example, you can create a variable which is also a function like this:
var myStepFunction = chooseStepFunction(true)
myStepFunction(4)
The benefit of nested function is really nice. For example, let's say you are building an app for the calculator, you can have all your logic in one function, as the following:
func doOperation(operation: String) -> ((Double, Double) -> Double)? {
func plus(s: Double, d: Double) -> Double {
return s + d
}
func min(s: Double, d: Double) -> Double{
return s - d
}
switch operation {
case "+":
return plus
case "-" :
return min
default :
return nil
}
}
var myOperationFunction = doOperation("-")?(4, 4) // 0
var myOperationFunction2 = doOperation("+")?(4, 5) //9
In some cases, you are not allowed to see the implementation of some function, or not responsible for them. Then hidding them inside other function is really a good approach. For instance, assume that you colleague is reaponsible for developing the plus and min functions, he/she will do that, and you just use the outer function.
It is deferent from closure, because in clouser, you pass your logic to other logic, which will call yours. It is kind of plugin. For instance, after calling the http request, you can pass the code that you want your app to do when receiving the response from the server

Related

What is the difference between "lazy var funcName: () -> Void" and regular function declaration in Swift

I have recently encountered such code block when I was working on a different codebase.
I was wondering is there any significant difference (in terms of memory impact etc.) between these two declarations other than syntactic ease? I regularly use lazy stored properties but I couldn't visualize how a function can be "lazy". Can you guys also enlighten me how functions are processed (or share an article explaining this topic) by the swift compiler as well?
Thanks in advance, wish you bug free codes.
A few differences I can think of off the top of my head:
With functions, you can use parameter labels to make the call site more readable, but since you can't add parameter labels to function types, you can't do that with the lazy var declaration.
// doesn't work
lazy var say: (message: String, to person: String) -> Void = {
...
}
// works
func say(message: String, to person: String) {
...
}
You can only invoke a function type with no parameter labels at all :( say("Hello", "Sweeper") instead of say(message: "Hello", to: "Sweeper").
lazy vars are variables, so someone could just change them:
helloFunc = { /* something else */ }
you could prevent this by adding a private setter, but that still allows setting it from within the same class. With a function, its implementation can never be changed at runtime.
lazy vars cannot be generic. Functions can.
// doesn't work
lazy var someGenericThing<T>: (T) -> Void = {
...
}
// works
func someGenericThing<T>(x: T) {
...
}
You might be able to work around this by making the enclosing type generic, but that changes the semantics of the entire type. With functions, you don't need to do that at all.
If you're implementing a language, the magic you need to implement 'lazy' as a feature is to make the value provided silently be wrapped in a function (of no arguments) that is automatically evaluated the first time the property is read.
So for example if you have
var x = SomeObject() // eagerly construct an instance of SomeObject
and
lazy var x = SomeObject() // construct an instance if/when someone reads x
behind the scenes you have, for the lazy var x, either x has not yet been read, or it has been and therefore has a value. So this is like
enum Lazy<T> {
case notReadYet(() -> T) // either you have a function that makes the initial T
case read(T) // or you have a value for T
}
var thing: Lazy<SomeObject> = .notReadYet { return SomeObject() }
and with a suitable property wrapper or other language magic, wrap the calls to the getter for thing with a switch on the case, which checks if you are in the notReadYet case, and if so automatically invoke the function to produce the T and then set the property to .read(t) for the particular value of t.
If you substitute in your type: () -> Void from your example you have something like:
var thing: Lazy<() -> Void> = .notReadYet({ return { print("Hello") } })
This is all rather odd because it's a void value and not much point making it lazy, e.g. it's not expensive to compute; it doesn't help break a two-phase initialisation loop, so why do it?

Swift Passing a Generic from a Function

I have the following function :
Amplify.API.query(request: .get(
self.getObjectForOCObject(ocObject: ocObject)!, byId: id)) { event in
The definition of the get function is :
public static func get<M: Model>(_ modelType: M.Type,
byId id: String) -> GraphQLRequest<M?> {
My getObjectForObject is as follows :
func getObjectForOCObject <M: Model>(ocObject:NSObject) -> M.Type?
{
if type (of:ocObject) == type(of: OCAccount.self)
{
return Account.self as? M.Type
}
return nil;
}
But I'm getting a"Generic Parameter 'M' could not be inferred. I get that the compiler cannot determine what type of object this is. However I don't know how to fix this. I need my getObjectForOCObject function to return what it is expecting. Essentially I'm trying to return the type of object based on the type of another object.
Normally this call is done this way and it works...
Amplify.API.query(request: .get(Account.self, byId: id)) { event in
I'm trying to avoid having to create a number of functions to handle each different Model in my code as that is being handled in higher up in the call hierarchy. Which is why I'm trying to do this. Otherwise I'm going to have to write essentially the same code in multiple places. In Objective C one can use the super class to pass objects around but the inheriting class still comes along with it. But with Swift being dynamically typed, I'm running into this issue.
The closest I've gotten is this... Changing the getObjectForOCObject return to Model.Type? as so :
func getObjectForOCObject (ocObject:NSObject) -> Model.Type?
{
if type (of:ocObject) == type(of: OCAccount.self)
{
return Account.self
}
return nil;
}
Then I get a Cannot convert value of type 'Model.Type?' to expected argument type 'M.Type' But aren't these essentially the same thing based on the .get function above?
Hoping for some insight here. Also, FYI, I'm pretty terrible with Swift so I'm certain I'm definitely doing some bad things in Swift here. I'm an expert with ObjC. I'm just trying to create a bridge between the two for this Swift library I'm using.

what is the difference between these two in swift 3 [duplicate]

In the Introduction to Swift WWDC session, a read-only property description is demonstrated:
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description)
Are there any implications to choosing the above approach over using a method instead:
class Vehicle {
var numberOfWheels = 0
func description() -> String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description())
It seems to me that the most obvious reasons for choosing a read-only computed property are:
Semantics - in this example it makes sense for description to be a property of the class, rather than an action it performs.
Brevity/Clarity - prevents the need to use empty parentheses when getting the value.
Clearly the above example is overly simple, but are there other good reasons to choose one over the other? For example, are there some features of functions or properties that would guide your decision of which to use?
N.B. At first glance this seems like quite a common OOP question, but I'm keen to know of any Swift-specific features that would guide best practice when using this language.
It seems to me that it's mostly a matter of style: I strongly prefer using properties for just that: properties; meaning simple values that you can get and/or set. I use functions (or methods) when actual work is being done. Maybe something has to be computed or read from disk or from a database: In this case I use a function, even when only a simple value is returned. That way I can easily see whether a call is cheap (properties) or possibly expensive (functions).
We will probably get more clarity when Apple publishes some Swift coding conventions.
Well, you can apply Kotlin 's advices https://kotlinlang.org/docs/reference/coding-conventions.html#functions-vs-properties.
In some cases functions with no arguments might be interchangeable
with read-only properties. Although the semantics are similar, there
are some stylistic conventions on when to prefer one to another.
Prefer a property over a function when the underlying algorithm:
does not throw
complexity is cheap to calculate (or caсhed
on the first run)
returns the same result over invocations
While a question of computed properties vs methods in general is hard and subjective, currently there is one important argument in the Swift's case for preferring methods over properties. You can use methods in Swift as pure functions which is not true for properties (as of Swift 2.0 beta). This makes methods much more powerful and useful since they can participate in functional composition.
func fflat<A, R>(f: (A) -> () -> (R)) -> (A) -> (R) {
return { f($0)() }
}
func fnot<A>(f: (A) -> Bool) -> (A) -> (Bool) {
return { !f($0) }
}
extension String {
func isEmptyAsFunc() -> Bool {
return isEmpty
}
}
let strings = ["Hello", "", "world"]
strings.filter(fnot(fflat(String.isEmptyAsFunc)))
There is a difference:
If you use a property you can then eventually override it and make it read/write in a subclass.
Since the runtime is the same, this question applies to Objective-C as well. I'd say, with properties you get
a possibility of adding a setter in a subclass, making the property readwrite
an ability to use KVO/didSet for change notifications
more generally, you can pass property to methods that expect key paths, e.g. fetch request sorting
As for something specific to Swift, the only example I have is that you can use #lazy for a property.
In the read-only case, a computed property should not be considered semantically equivalent to a method, even when they behave identically, because dropping the func declaration blurs the distinction between quantities that comprise the state of an instance and quantities that are merely functions of the state. You save typing () at the call site, but risk losing clarity in your code.
As a trivial example, consider the following vector type:
struct Vector {
let x, y: Double
func length() -> Double {
return sqrt(x*x + y*y)
}
}
By declaring the length as a method, it’s clear that it’s a function of the state, which depends only on x and y.
On the other hand, if you were to express length as a computed property
struct VectorWithLengthAsProperty {
let x, y: Double
var length: Double {
return sqrt(x*x + y*y)
}
}
then when you dot-tab-complete in your IDE on an instance of VectorWithLengthAsProperty, it would look as if x, y, length were properties on an equal footing, which is conceptually incorrect.
From the performance perspective, there seems no difference. As you can see in the benchmark result.
gist
main.swift code snippet:
import Foundation
class MyClass {
var prop: Int {
return 88
}
func foo() -> Int {
return 88
}
}
func test(times: u_long) {
func testProp(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = Date()
for _ in 0...times {
_ = myClass.prop
}
let ending = Date()
return ending.timeIntervalSince(starting)
}
func testFunc(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = Date()
for _ in 0...times {
_ = myClass.prop
}
let ending = Date()
return ending.timeIntervalSince(starting)
}
print("prop: \(testProp(times: times))")
print("func: \(testFunc(times: times))")
}
test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)
Output:
prop: 0.0380070209503174
func: 0.0350250005722046
prop: 0.371925950050354
func: 0.363085985183716
prop: 3.4023300409317
func: 3.38373708724976
prop: 33.5842199325562
func: 34.8433820009232
Program ended with exit code: 0
In Chart:
There are situations where you would prefer computed property over normal functions. Such as: returning the full name of an person. You already know the first name and the last name. So really the fullName property is a property not a function. In this case, it is computed property (because you can't set the full name, you can just extract it using the firstname and the lastname)
class Person{
let firstName: String
let lastName: String
init(firstName: String, lastName: String){
self.firstName = firstName
self.lastName = lastName
}
var fullName :String{
return firstName+" "+lastName
}
}
let william = Person(firstName: "William", lastName: "Kinaan")
william.fullName //William Kinaan
Semantically speaking, computed properties should be tightly coupled with the intrinsic state of the object - if other properties don't change, then querying the computed property at different times should give the same output (comparable via == or ===) - similar to calling a pure function on that object.
Methods on the other hand come out of the box with the assumption that we might not always get the same results, because Swift doesn't have a way to mark functions as pure. Also, methods in OOP are considered actions, which means that executing them might result in side effects. If the method has no side effects, then it can safely be converted to a computed property.
Note that both of the above statements are purely from a semantic perspective, as it might well happen for computed properties to have side effects that we don't expect, and methods to be pure.
Historically description is a property on NSObject and many would expect that it continues the same in Swift. Adding parens after it will only add confusion.
EDIT:
After furious downvoting I have to clarify something - if it is accessed via dot syntax, it can be considered a property. It doesn't matter what's under the hood. You can't access usual methods with dot syntax.
Besides, calling this property did not require extra parens, like in the case of Swift, which may lead to confusion.
An updated/fixed version of Benjamin Wen's answer incorporating Cristik's suggestion.
class MyClass {
var prop: Int {
return 88
}
func foo() -> Int {
return 88
}
}
func test(times: u_long) {
func testProp(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = CACurrentMediaTime()
for _ in 0...times {
_ = myClass.prop
}
let ending = CACurrentMediaTime()
return ending - starting
}
func testFunc(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = CACurrentMediaTime()
for _ in 0...times {
_ = myClass.foo()
}
let ending = CACurrentMediaTime()
return ending - starting
}
print("prop: \(testProp(times: times))")
print("func: \(testFunc(times: times))")
}
test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)

How send generic value through the function? [duplicate]

I have code that follows the general design of:
protocol DispatchType {}
class DispatchType1: DispatchType {}
class DispatchType2: DispatchType {}
func doBar<D:DispatchType>(value:D) {
print("general function called")
}
func doBar(value:DispatchType1) {
print("DispatchType1 called")
}
func doBar(value:DispatchType2) {
print("DispatchType2 called")
}
where in reality DispatchType is actually a backend storage. The doBarfunctions are optimized methods that depend on the correct storage type. Everything works fine if I do:
let d1 = DispatchType1()
let d2 = DispatchType2()
doBar(value: d1) // "DispatchType1 called"
doBar(value: d2) // "DispatchType2 called"
However, if I make a function that calls doBar:
func test<D:DispatchType>(value:D) {
doBar(value: value)
}
and I try a similar calling pattern, I get:
test(value: d1) // "general function called"
test(value: d2) // "general function called"
This seems like something that Swift should be able to handle since it should be able to determine at compile time the type constraints. Just as a quick test, I also tried writing doBar as:
func doBar<D:DispatchType>(value:D) where D:DispatchType1 {
print("DispatchType1 called")
}
func doBar<D:DispatchType>(value:D) where D:DispatchType2 {
print("DispatchType2 called")
}
but get the same results.
Any ideas if this is correct Swift behavior, and if so, a good way to get around this behavior?
Edit 1: Example of why I was trying to avoid using protocols. Suppose I have the code (greatly simplified from my actual code):
protocol Storage {
// ...
}
class Tensor<S:Storage> {
// ...
}
For the Tensor class I have a base set of operations that can be performed on the Tensors. However, the operations themselves will change their behavior based on the storage. Currently I accomplish this with:
func dot<S:Storage>(_ lhs:Tensor<S>, _ rhs:Tensor<S>) -> Tensor<S> { ... }
While I can put these in the Tensor class and use extensions:
extension Tensor where S:CBlasStorage {
func dot(_ tensor:Tensor<S>) -> Tensor<S> {
// ...
}
}
this has a few side effects which I don't like:
I think dot(lhs, rhs) is preferable to lhs.dot(rhs). Convenience functions can be written to get around this, but that will create a huge explosion of code.
This will cause the Tensor class to become monolithic. I really prefer having it contain the minimal amount of code necessary and expand its functionality by auxiliary functions.
Related to (2), this means that anyone who wants to add new functionality will have to touch the base class, which I consider bad design.
Edit 2: One alternative is that things work expected if you use constraints for everything:
func test<D:DispatchType>(value:D) where D:DispatchType1 {
doBar(value: value)
}
func test<D:DispatchType>(value:D) where D:DispatchType2 {
doBar(value: value)
}
will cause the correct doBar to be called. This also isn't ideal, as it will cause a lot of extra code to be written, but at least lets me keep my current design.
Edit 3: I came across documentation showing the use of static keyword with generics. This helps at least with point (1):
class Tensor<S:Storage> {
// ...
static func cos(_ tensor:Tensor<S>) -> Tensor<S> {
// ...
}
}
allows you to write:
let result = Tensor.cos(value)
and it supports operator overloading:
let result = value1 + value2
it does have the added verbosity of required Tensor. This can made a little better with:
typealias T<S:Storage> = Tensor<S>
This is indeed correct behaviour as overload resolution takes place at compile time (it would be a pretty expensive operation to take place at runtime). Therefore from within test(value:), the only thing the compiler knows about value is that it's of some type that conforms to DispatchType – thus the only overload it can dispatch to is func doBar<D : DispatchType>(value: D).
Things would be different if generic functions were always specialised by the compiler, because then a specialised implementation of test(value:) would know the concrete type of value and thus be able to pick the appropriate overload. However, specialisation of generic functions is currently only an optimisation (as without inlining, it can add significant bloat to your code), so this doesn't change the observed behaviour.
One solution in order to allow for polymorphism is to leverage the protocol witness table (see this great WWDC talk on them) by adding doBar() as a protocol requirement, and implementing the specialised implementations of it in the respective classes that conform to the protocol, with the general implementation being a part of the protocol extension.
This will allow for the dynamic dispatch of doBar(), thus allowing it to be called from test(value:) and having the correct implementation called.
protocol DispatchType {
func doBar()
}
extension DispatchType {
func doBar() {
print("general function called")
}
}
class DispatchType1: DispatchType {
func doBar() {
print("DispatchType1 called")
}
}
class DispatchType2: DispatchType {
func doBar() {
print("DispatchType2 called")
}
}
func test<D : DispatchType>(value: D) {
value.doBar()
}
let d1 = DispatchType1()
let d2 = DispatchType2()
test(value: d1) // "DispatchType1 called"
test(value: d2) // "DispatchType2 called"

Swift 3 nested functions vs closures

I have a large method that does some loading and calculating so it shows an activity indicator view to inform the users they should wait. The logic is pretty complex so there are 4 places in which the data processing might break or return (everything is done on closures). Anyway, I didn't want to repeat this code:
DispatchQueue.main.async {
activityView.hide()
activityView.removeFromSuperview()
}
in 4 places so I figured that I would write a nested function:
func removeActivityView() {
DispatchQueue.main.async {
activityView.hide()
activityView.removeFromSuperview()
}
}
but then I realised that in Swift I could also do:
let removeActivityView = {
DispatchQueue.main.async {
activityView.hide()
activityView.removeFromSuperview()
}
}
which is used exactly in the same way and does exactly the same from the user's point of view.
So what is the actual difference between one approach and the other?
They are the same in this case. In Swift:
Nested functions are closures that have a name and can capture values from their enclosing function.
Source
In fact, you could also do:
func foo() {
print("Foo!")
}
let bar = foo
Now foo() and bar() would yield the same result. This can be done for any function that takes in no arguments.
I'm not sure how/if the compiler differentiates these two. If anyone has more information with respect to that, I would be very interested!