Need help understanding how these two statements are equal - swift

Here is a block of code that is equivalent (to my knowledge) to the other.
let f:()->() = brick
where brick is
func brick()->Void{ print("Throw Brick");}
but I can also write it as
let f = {return brick()}
What is this ^ code doing.
The first code I know makes sense to me. This is where I am defining a variable who's type is of the signature ()->() or ()->Void. And then passing the reference of brick function to the variable.
Thanks

Though in both code snippets, f will behave in the same way when you call it, the code snippets are semantically different.
let f:()->() = brick
This assigns the function brick to the let constant f. Note that the type annotation is not required since the compiler knows that brick is a function that takes no parameters and returns Void, so it can infer that f must also be such a function too. Therefore, you can write it as:
let f = brick
Another way to write functions is to use a closure expression. For example, the following closure expression represents a function that calls brick:
{ return brick() }
Since you omitted the in keyword and didn't use any shorthand argument names ($0, $1 etc), the compiler infers that the closure expression takes no arguments. And since brick() returns Void, the closure expression returns Void too - return brick() means "return what brick() returns". The compiler is able to infer the type of the closure expression, so this is valid:
let f = { return brick() }
This assigns a "closure expression that calls simply calls brick() and returns what it returns" to f.
Depending on how you look at it, this is a bit different from let f = brick, where you are directly assigning brick to f. But in the end, in both cases calling f will do the same thing - you will end up calling brick.
The difference is sort of similar to the difference between let x: Double = 1 and let x = cos(0) - x = 1 in both cases, but one of those ways is more direct.

First of all your two versions are not equivalent. This:
func brick()->Void{ print("Throw Brick");}
let f = {return brick()}
is equated by this:
func brick()->Void{ print("Throw Brick");}
func brickCaller() { return brick() }
let f = brickCaller
Whereas, the equivalent of your
let f:()->() = brick
func brick()->Void{ print("Throw Brick");}
would be simply
let f:()->() = { print("Throw Brick") }
with no intermediary call to brick at all.
So, anyway, I'd put it differently from Sweeper's answer. I'd reply that a function can be declared-with-a-name, using func, or be nameless (anonymous), using a mere function body.
So the point is that in each pair of equivalents, one function has a name-and-declaration of its own, with func, and the other function doesn't — its body is simply assigned directly to the variable f.

Related

I'm confused about value type () in Swift. What is it, and how am I meant to use it?

I'm trying to convert height in feet with a decimal to height in feet and inches.
I'm trying to use the .round(.down) method to get the feet, and multiply the decimal by 12 for the inches. I'm getting all kinds of errors, like so:
var heightInFeet: Float = 5.45
let feetRounded = heightInFeet.round(.down) // feetRounded is "type ()." What is that?
percentToNextFoot = heightInFeet - feetRounded // Error: Binary operator '-' cannot be applied to operands of type 'Float' and '()'
I tried the following and got another error:
percentToNextFoot = heightInFeet - Float(feetRounded) // Cannot invoke initializer for type 'Float' with an argument list of type '(())'
I finally got it working by avoiding the .round() method, but I'm still really confused by the value type (). Can anyone explain what's going on here?:
var heightInFeet: Float = 5.45
var feet = Int(heightInFeet) // 5
var percentToNextFoot = heightInFeet - Float(feet) // 0.45
let heightInFeetAndInches = "\(feet)ft \(Int(percentToNextFoot * 12))in" // 5ft 5in
() is shorthand for void. It means "no value is possible here".
In this example, it means that the .round() method does not return anything - it is a mutating function called on its receiver. So assigning its void return to a var causes that var's type to be inferred to be void. Void vars can be useful, sometimes, rarely*, but not in this case.
Methods on value types often come in pairs: a verb like round, and a passive verb e.g. rounded. The first operates directly on, and modifies, its target; the second returns a modified version of its target. For another example, see sort() and sorted() on collections, or append(_) and appending(_) on strings, etc.
(* note: filter is an annoying exception; it means "filtered", and there is no handy "filter in place".)
To get the effect you were going for in the first example, rounded() is what you want.
--
(* To answer the tangential question in your title: how would one actually use a void variable? Well, here's a way I use them sometimes:
In an object with some setup that I would like to happen sometime after init, but guaranteed at most once per instance, I used to use Objective-C's dispatch_once. That's not available in Swift, so now I'll make a lazy void member like so:
class Foo {
lazy var setup: () = {
// do some complicated stuff I couldn't do in `init` for some reason
// this will only run once
}()
func doSomethingUseful() {
_ = setup // runs the setup initializer just the first time we get here
// do useful things that depend on setup having happened
}
}
I'll leave it to the comments to judge whether we're "meant to" use such a technique. :)
Welcome to stack overflow!
Double has two rounding methods:
Double.round(), which rounds a Double value by mutating it in-place. This is one you called. It doesn't return anything, which strictly speaking means it returns Void, a.k.a. (), the empty tuple.
Double.rounded(), which rounds a Double value by returning a new Double. This is the one you probably intended to call.
By calling the first, and trying to assign the value to a variable, you end up with a variable of type Void, whose value is ().
This is a common Swift convention: "object.foo" edits it in place. "object.fooed" returns a mutated copy.
That said, in your case, I would recommend doing this using the existing Measurement API:
import Foundation
extension Measurement where UnitType == UnitLength {
func toFeetAndInches() -> (feet: Measurement<UnitLength>, inches: Measurement<UnitLength>) {
let numberOfWholeFeet = self.converted(to: .feet).value.rounded(.towardZero)
return (
feet: Measurement(value: numberOfWholeFeet, unit: UnitLength.feet),
inches: Measurement(value: self.value - numberOfWholeFeet, unit: UnitLength.feet).converted(to: .inches)
)
}
}
let heightInFeet = Measurement(value: 5.5, unit: UnitLength.feet)
let (feet, inches) = heightInFeet.toFeetAndInches()
let mf = MeasurementFormatter()
mf.unitOptions = .providedUnit // force the use of feet/inches, rather than the unit appropriate for the user's locale.
mf.unitStyle = .medium
print(mf.string(for: feet)!, mf.string(for: inches)!) // => "5 ft. 6 in."
If you look at the reference for the round function of Float type, you will see that it returns nothing. It just mutate the float you called this method on.
You can do
var feetRounded = heightInFeet
feetRounded.round(.down)
Please take a look at the documentation. The method
mutating func round(_ rule: FloatingPointRoundingRule)
has no return value (aka Void aka ())
If you need a result you have to use rounded(_:) which has a return value
func rounded(_ rule: FloatingPointRoundingRule) -> Float
round changes the value in place; you use it like this:
var heightInFeet: Float = 5.45
heightInFeet.round(.down)
You notice that no value is returned; there is no = in the second line. We do not need to set anything to the result of the round call, because it has no result.
If, as in your code, you accidentally do capture the "result", it is expressed as type (). So () is the "result" type of a method call that has no result.
When we accidentally write this:
var heightInFeet: Float = 5.45
let x = heightInFeet.round(.down)
we get this error: "Constant 'x' inferred to have type '()', which may be unexpected." That is just a fancy way of saying, "You've taken a method call that has no result and captured its 'result'. You probably didn't mean to do that!" And indeed, you didn't.

How come I can create a variable with same name as a function parameter?

In a function, if I'm being passed an int (which is immutable type, i.e let n), how come if I pass this into a function, I can create a var variable of this? Just wondering why swift works this way, and the reason for it .
func checkNum(_ n: Int) -> Bool {
var n = n
}
In this, it let's me do this.
This is called "shadowing" and is allowed in a variety of places because it's convenient for the programmer because it avoids having two similarly named variables in scope. Without this feature, this code would be:
func checkNum(_ n: Int) -> Bool {
var writableN = n
...
}
This raises the possibility of modifying writableN, and then using n again later in the function unintentionally. It also can make the function a bit harder to understand because of the extra variable. (Of course shadowing can also make code more difficult to understand as well, if it's used without care.)
This is very similar to the if let shadowing, such as:
var x: Int? = ...
if let x = x { ... }
This allows you to use x inside the if let as a non-Optional rather than having to come up with some other name for it.
This is a fairly general feature. Whenever there is a new scope, variables can shadow. For example, you can declare variables inside a function that have the same name as properties or globals. You can create scopes inside a function as well
func checkNum(_ n: Int) -> Bool {
var n = n // Shadows previous `let`
do {
let n = 4 // Shadows previous `var`
print(n)
}
return true
}
Used with care, this is helpful. Used too often (as this last example definitely does), it can make the code very confusing.
Your specific case touches on another important aspect of Swift, which is that it tries to control shared mutable state. The n that the function receives is a copy of the integer that was passed. Modifying n would never directly modify the caller's variable. (There's inout to allow this, but it's subtle. It does't share state. It copies the value in, and on return, copies the value back out.)
Since n isn't shared with the caller, Swift makes this very explicit by making it immutable. If you want to modify it, you need to explicitly make another copy, and var n = n does that.
'var' as a parameter attribute has been deprecated in Swift 3 so that is no longer possible. You can get a similar behaviour by using an inout parameter
func checkNum(_ n: inout Int) -> Bool {
n + 1
}
Remember to call the function by passing the parameter like this: checkNum(&n)

How does a function that returns a function work?

I'm reading Apple's book about Swift and stumbled upon this piece of code, which I after many tries couldn't understand. As far as I understand, this function returns a function. The two last lines of code, as well as all the code, though, are totally bewildering. And how we can assign a function to a variable (the seventh line)? Thank you.
I've typed it myself into the Playground but still don't get it.
func makeIncrement () -> ((Int) -> Int){
func addOne (number: Int) -> Int{
return 1 + number
}
return addOne
}
var increment = makeIncrement()
increment(7)
Functions can be considered objects in Swift (or as first class functions - worth researching).
Therefore may be assigned to variables and to object properties.
So in your code makeIncrement simply returns the function addOne as a variable.
var increment = makeIncrement() can just be seen as assigning the returned function from makeIncrement as a variable (or function object) increment.
We can then freely call the increment function as we would call addOneor any other function really.
A function is something with optional input and a return type. If you alt-click on the var increment you will see that increment is of type ((Int) -> Int). This means that you can input an Int and will return an Int. This is then done in the last line by calling this function.
If you know object-oriented programming, you will know that you can always pass objects around, which also have functions. In this way, in your code, it is doing the same but now we are omitting the object.

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).

What does an ampersand (&) mean in the Swift language?

I know about the ampersand as a bit operation but sometimes I see it in front of variable names. What does putting an & in front of variables do?
It works as an inout to make the variable an in-out parameter. In-out means in fact passing value by reference, not by value. And it requires not only to accept value by reference, by also to pass it by reference, so pass it with & - foo(&myVar) instead of just foo(myVar)
As you see you can use that in error handing in Swift where you have to create an error reference and pass it to the function using & the function will populate the error value if an error occur or pass the variable back as it was before
Why do we use it? Sometimes a function already returns other values and just returning another one (like an error) would be confusing, so we pass it as an inout. Other times we want the values to be populated by the function so we don't have to iterate over lots of return values, since the function already did it for us - among other possible uses.
It means that it is an in-out variable. You can do something directly with that variable. It is passed by address, not as a copy.
For example:
var temp = 10
func add(inout a: Int){
a++
}
add(inout:&temp)
temp // 11
There's another function of the ampersand in the Swift language that hasn't been mentioned yet. Take the following example:
protocol Foo {}
protocol Bar {}
func myMethod(myVar: Foo & Bar) {
// Do something
}
Here the ampersand syntax is stating that myVar conforms to both the Foo and Bar protocol.
As another use case, consider the following:
func myMethod() -> UIViewController & UITableViewDataSource {
// Do something
}
Here we're saying that the method returns a class instance (of UIViewController) that conforms to a certain protocol (UITableViewDataSource). This is rendered somewhat obsolete with Swift 5.1's Opaque Types but you may see this syntax in pre-Swift 5.1 code from time to time.
If you put & before a variable in a function, that means this variable is inout variable.
#Icaro already described what it means, I will just give an example to illustrate the difference between inout variables and in variables:
func majec(inout xValue:Int, var yValue:Int) {
xValue = 100
yValue = 200
}
var xValue = 33
var yValue = 33
majec(&xValue, yValue: yValue)
xValue //100
yValue //33
As noted in other answers, you use prefix & to pass a value to an inout parameter of a method or function call, as documented under Functions > Function Argument Labels and Parameter Names > In-Out Parameters in The Swift Programming Language. But there's more to it than that.
You can, in practice, think about Swift inout parameters and passing values to them as being similar to C or C++ pass-by-address or pass-by-reference. In fact, the compiler will optimize many uses of inout parameters down to roughly the same mechanics (especially when you're calling imported C or ObjC APIs that deal in pointers). However, those are just optimizations — at a semantic level, inout really doesn't pass addresses around, which frees the compiler to make this language construct more flexible and powerful.
For example, here's a struct that uses a common strategy for validating access to one of its properties:
struct Point {
private var _x: Int
var x: Int {
get {
print("get x: \(_x)")
return _x
}
set {
print("set x: \(newValue)")
_x = newValue
}
}
// ... same for y ...
init(x: Int, y: Int) { self._x = x; self._y = y }
}
(In "real" code, the getter and setter for x could do things like enforcing minimum/maximum values. Or x could do other computed-property tricks, like talking to a SQL database under the hood. Here we just instrument the call and get/set the underlying private property.)
Now, what happens when we pass x to an inout parameter?
func plusOne(num: inout Int) {
num += 1
}
var pt = Point(x: 0, y: 1)
plusOne(num: &pt.x)
// prints:
// get x: 0
// set x: 1
So, even though x is a computed property, passing it "by reference" using an inout parameter works the same as you'd expect it to if x were a stored property or a local variable.
This means that you can pass all sorts of things "by reference" that you couldn't even consider in C/C++/ObjC. For example, consider the standard library swap function, that takes any two... "things" and switches their values:
var a = 1, b = 2
swap(&a, &b)
print(a, b) // -> 2 1
var dict = [ "Malcolm": "Captain", "Kaylee": "Mechanic" ]
swap(&dict["Malcolm"], &dict["Kaylee"])
print(dict) // -> ["Kaylee": "Captain", "Malcolm": "Mechanic"], fanfic ahoy
let window1 = NSWindow()
let window2 = NSWindow()
window1.title = "window 1"
window2.title = "window 2"
var windows = [window1, window2]
swap(&windows[0], &windows[1])
print(windows.map { $0.title }) // -> ["window 2", "window 1"]
The the way inout works also lets you do fun stuff like using the += operator on nested call chains:
window.frame.origin.x += 10
... which is a whole lot simpler than decomposing a CGRect just to construct a new one with a different x coordinate.
This more nuanced version of the inout behavior, called "call by value result", and the ways it can optimize down to C-style "pass by address" behavior, is covered under Declarations > Functions > In-Out Parameters in The Swift Programming Language.