EDIT: I'm aware that I was using the wrong Xcode version for Swift 2, now. Problem solved.
I'm following the Swift 2 book from Apple. At a point there's the following example:
import Foundation
func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, condition: lessThanTen)
What I think is weird is the last line. Why does it say condition: lessThanTen and not just lessThanTen? My compiler (Xcode) also gives me an error doing it the way it's shown in the book.
Also: why does it only say list: [Int] in the third line but condition: Int -> Bool? Why not something like list: [Int] -> Int?
Swift functions and methods can define their parameters to either have external names or not.
By default, the first parameter omits its external name, and the
second and subsequent parameters use their local name as their
external name.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2 Prerelease).” iBooks. https://itun.es/us/k5SW7.l
The the tag condition: is the external name for the closure that you are passing to your hasAnyMatches function.
That code should compile and run.
My compiler (Xcode) also gives me an error doing it the way it's shown in the book.
Because the language has changed! In Swift 2, which you are reading about, the function has condition: so your call must have condition:. But you are testing in Swift 1.2, a very different language, where the rules are not the same.
In Swift 1.2, a top-level function declared with condition: means that your call should not have condition:. In Swift 1.2, to require the call to have condition:, the function declaration would have to say # condition:.
You are confusing yourself. Update Xcode so that the language you are using is the same as the language you are reading about.
It says condition: lessThanTen because in Swift you can define "labels", that is, descriptions for the data that a function call requires. It gives you an error because the call would be correct if the function declaration was func hasAnyMatches(list: [Int], #condition: Int -> Bool) -> Bool (at least this would be the case with Swift 1.2). The number sign produces, inside every call to the function, a label identical to the name of the function argument. Said label must not be deleted from the call, since it's there to clarify the purpose of that parameter to whoever invokes the function.
list: [Int] means that the first function argument takes name "list" and is of type [Int]. condition: Int -> Bool means that the second function argument takes name "condition" and is of type "Int to Bool", that is, condition is a function that takes a single argument of type Int and returns a value of type Bool. In fact, if you read the last line, in the call to the function hasAnyMatches the following are passed: i) an array of Ints and ii) a function that takes an Int and returns a Bool (note that when passing functions as parameters we only write their name - no parentheses).
Related
When passing a class or primitive type into a function, any change made in the function to the parameter will be reflected outside of the class. This is basically the same thing an inout parameter is supposed to do.
What is a good use case for an inout parameter?
inout means that modifying the local variable will also modify the passed-in parameters. Without it, the passed-in parameters will remain the same value. Trying to think of reference type when you are using inout and value type without using it.
For example:
import UIKit
var num1: Int = 1
var char1: Character = "a"
func changeNumber(var num: Int) {
num = 2
print(num) // 2
print(num1) // 1
}
changeNumber(num1)
func changeChar(inout char: Character) {
char = "b"
print(char) // b
print(char1) // b
}
changeChar(&char1)
A good use case will be swap function that it will modify the passed-in parameters.
Swift 3+ Note: Starting in Swift 3, the inout keyword must come after the colon and before the type. For example, Swift 3+ now requires func changeChar(char: inout Character).
From Apple Language Reference: Declarations - In-Out Parameters:
As an optimization, when the argument is a value stored at a physical
address in memory, the same memory location is used both inside and
outside the function body. The optimized behavior is known as call by
reference; it satisfies all of the requirements of the copy-in
copy-out model while removing the overhead of copying. Do not depend
on the behavioral differences between copy-in copy-out and call by
reference.
If you have a function that takes a somewhat memory-wise large value type as argument (say, a large structure type) and that returns the same type, and finally where the function return is always used just to replace the caller argument, then inout is to prefer as associated function parameter.
Consider the example below, where comments describe why we would want to use inout over a regular type-in-return-type function here:
struct MyStruct {
private var myInt: Int = 1
// ... lots and lots of stored properties
mutating func increaseMyInt() {
myInt += 1
}
}
/* call to function _copies_ argument to function property 'myHugeStruct' (copy 1)
function property is mutated
function returns a copy of mutated property to caller (copy 2) */
func myFunc(var myHugeStruct: MyStruct) -> MyStruct {
myHugeStruct.increaseMyInt()
return myHugeStruct
}
/* call-by-reference, no value copy overhead due to inout opimization */
func myFuncWithLessCopyOverhead(inout myHugeStruct: MyStruct) {
myHugeStruct.increaseMyInt()
}
var a = MyStruct()
a = myFunc(a) // copy, copy: overhead
myFuncWithLessCopyOverhead(&a) // call by reference: no memory reallocation
Also, in the example above---disregarding memory issues---inout can be preferred simply as a good code practice of telling whomever read our code that we are mutating the function caller argument (implicitly shown by the ampersand & preceding the argument in the function call). The following summarises this quite neatly:
If you want a function to modify a parameter’s value, and you want
those changes to persist after the function call has ended, define
that parameter as an in-out parameter instead.
From Apple Language Guide: Functions - In-Out Parameters.
For details regarding inout and how it's actually handled in memory (name copy-in-copy-out is somewhat misleading...)---in additional to the links to the language guide above---see the following SO thread:
Using inout keyword: is the parameter passed-by-reference or by copy-in copy-out (/call by value result)
(Edit addition: An additional note)
The example given in the accepted answer by Lucas Huang above tries to---in the scope of the function using an inout argument---access the variables that were passed as the inout arguments. This is not recommended, and is explicitly warned not to do in the language ref:
Do not access the value that was passed as an in-out argument, even if
the original argument is available in the current scope. When the
function returns, your changes to the original are overwritten with
the value of the copy. Do not depend on the implementation of the
call-by-reference optimization to try to keep the changes from being
overwritten.
Now, the access in this case is "only" non-mutable, e.g. print(...), but all access like this should, by convention, be avoided.
At request from a commenter, I'll add an example to shine light upon why we shouldn't really do anything with "the value that was passed as an in-out argument".
struct MyStruct {
var myStructsIntProperty: Int = 1
mutating func myNotVeryThoughtThroughInoutFunction (inout myInt: Int) {
myStructsIntProperty += 1
/* What happens here? 'myInt' inout parameter is passed to this
function by argument 'myStructsIntProperty' from _this_ instance
of the MyStruct structure. Hence, we're trying to increase the
value of the inout argument. Since the swift docs describe inout
as a "call by reference" type as well as a "copy-in-copy-out"
method, this behaviour is somewhat undefined (at least avoidable).
After the function has been called: will the value of
myStructsIntProperty have been increased by 1 or 2? (answer: 1) */
myInt += 1
}
func myInoutFunction (inout myInt: Int) {
myInt += 1
}
}
var a = MyStruct()
print(a.myStructsIntProperty) // 1
a.myInoutFunction(&a.myStructsIntProperty)
print(a.myStructsIntProperty) // 2
a.myNotVeryThoughtThroughInoutFunction(&a.myStructsIntProperty)
print(a.myStructsIntProperty) // 3 or 4? prints 3.
So, in this case, the inout behaves as copy-in-copy-out (and not by reference). We summarize by repeating the following statement from the language ref docs:
Do not depend on the behavioral differences between copy-in copy-out
and call by reference.
Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake. If you want a function to modify a parameter’s value, and you want those changes to persist after the function call has ended, define that parameter as an in-out parameter instead.
inout param: modifies passing and local variable values.
func doubleInPlace(number: inout Int) {
number *= 2
print(number)
}
var myNum = 10 doubleInPlace(number: &myNum)
inout parameter allow us to change the data of a value type parameter and to keep changes still after the function call has finished.
If you work with classes then, as you say, you can modify the class because the parameter is a reference to the class. But this won't work when your parameter is a value type (https://docs.swift.org/swift-book/LanguageGuide/Functions.html - In-Out Parameters Section)
One good example of using inout is this one (defining math for CGPoints):
func + (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x + right.x, y: left.y + right.y)
}
func += (left: inout CGPoint, right: CGPoint) {
left = left + right
}
Basically it is useful when you want to play with addresses of variable its very useful in data structure algorithms
when use inout parameter swift 4.0 Work
class ViewController: UIViewController {
var total:Int = 100
override func viewDidLoad() {
super.viewDidLoad()
self.paramTotal(total1: &total)
}
func paramTotal(total1 :inout Int) {
total1 = 111
print("Total1 ==> \(total1)")
print("Total ==> \(total)")
}
}
I've done some searching and can't seem to find a solution for my below issue. I'm fairly new to swift so working through some issues. I have the below function which is just a stub containing the signature of the function and a return value just to get it to compile.
The test code is what I've been given, I did not write this and unfortunately cannot alter it.
My issues is that when I run it, it says that the test that calls this function has an "Ambiguous call to member '=='". I cannot alter the test code. Whatever the issue is must be in my function signature i'm assuming but could use some help.
Function That I am writing (That I assume contains the issue):
func contains(target: StringOrInt, compare: Character ) -> Bool {
return false
} // contains
Test that calls the function (I'm not allowed to edit this and did not write it):
func test_contains_cons_2_strings_3() {
let list1 = MyList.cons("foo", MyList.cons("bar", MyList.empty))
assertEquals(testName: "test_contains_cons_2_strings_3",
expected: true,
received: list1.contains(target: "bar", compare: ==))//Error is on this line '=='
} // test_contains_cons_2_strings_3
Error:
main.swift:807:67: error: ambiguous reference to member '=='
received: list1.contains(target: "foo", compare: ==))
Also note that "StringOrInt" is a protocol that I've defined that acts as an extension on both Int and String. This is done because the test code (Which i did not write and cannot edit) passes both strings and ints to this same variable and function.
Thanks advance for any help, I really appreciate it!
I think you want to compare two strings by passing "==" operator and return a Boolean value.If so you can use the below method,
func myList(_ compare:((String, String) -> Bool)) -> Bool {
return compare("foo","bar")
}
myList(==)
I was able to figure this out using the below. I implemented an enum of generic type and the nan extension on that enum. I then used this generic type within the contains function to represent multiple types instead of StringOrInt. Thanks everyone for the comments and the help.
enum implemented:
indirect enum my_list<A> {
case cons(A, my_list<A>)
case empty
}
I then implemented in extension for this enum "extension my_list" and placed the contains function within the extension.
contains function signature/stub:
func contains(target: A, compare:((A, A) -> Bool))
-> Bool {
return true
}// contains
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.
In Swift 2, it appears that the first parameter name is not always required when calling a function. Now in Swift 3, the first parameter name is required when calling the function. For example:
func frobnicate(runcible: String) {
print("Frobnicate: \(runcible)")
}
Swift 2.2 allowed the function to be called by simply typing:
Frobnicate("Station")
Swift 3 seems to be requiring that we use the first parameter names of methods such as:
Frobnicate(runcible:"Station")
Is this the case with Swift 3 for all functions and methods or just certain situations?
Yes, this is right. Swift is fixing a language inconsistency this way (this was always required for initializers).
If you don't want to use the external parameter name, just remove it explicitly:
func frobnicate(_ runcible: String) {
print("Frobnicate: \(runcible)")
}
You can read the full rationale in Swift Evolution 0046
You can read The Swift Programming Language (Swift 3) in i-Book. Also you can check this out in WWDC 2016: What's New in Swift
In Swift 3, by default, functions use their parameter names as labels for their arguments. Write a custom argument label before the parameter name, or write _ to use no argument label.
fun greet(_ person: String, on day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")
or
// This also works with Swift 2
fun addThreeNumber(_ first: Int, _ second: Int, _ third: Int) {
print(first+second+third)
}
addThreeNumber(1, 2, 3)
Exactly. In Swift 3.0, it's mandatory to write parameter names for all the parameters (including the first parameter). Parameter name is the one which is used inside the function implementation body.
func frobnicate(runcible: String) {
print("Frobnicate: \(runcible)")
}
By default, the external parameter label is same as the parameter name, if you don't specify any parameter label explicitly. Parameter label is the one which is used to pass the arguments while calling the function. If you need, for better clarity purpose, you can also specify external parameter labels explicitly. Example below-
func frobnicate(runcibleExternalLabel runcible: String) {
print("Frobnicate: \(runcible)")
}
If you want to skip the external parameter label while calling the function, just prepend a "_" before the parameter name.
func frobnicate(_ runcible: String) {
print("Frobnicate: \(runcible)")
}
Yes Swift 3 requires you to send First Parameter Label.
Please refer Swift 3 changes
The reason you want labels for parameters is so other code can supply parameters in any order.
Without labels, when you call the function the parameters are anonymous and you cannot be certain if you have supplied them in the wrong order.
Place labels in front of the parameters and code tools can do a much better job at catching errors us humans put in.
The underscore is just a way to cope with the transition from legacy code; method names including an Implicit first parameter. You should change any underscores that migration adds to your code to an explicit parameter label. You know it makes sense.
When passing a class or primitive type into a function, any change made in the function to the parameter will be reflected outside of the class. This is basically the same thing an inout parameter is supposed to do.
What is a good use case for an inout parameter?
inout means that modifying the local variable will also modify the passed-in parameters. Without it, the passed-in parameters will remain the same value. Trying to think of reference type when you are using inout and value type without using it.
For example:
import UIKit
var num1: Int = 1
var char1: Character = "a"
func changeNumber(var num: Int) {
num = 2
print(num) // 2
print(num1) // 1
}
changeNumber(num1)
func changeChar(inout char: Character) {
char = "b"
print(char) // b
print(char1) // b
}
changeChar(&char1)
A good use case will be swap function that it will modify the passed-in parameters.
Swift 3+ Note: Starting in Swift 3, the inout keyword must come after the colon and before the type. For example, Swift 3+ now requires func changeChar(char: inout Character).
From Apple Language Reference: Declarations - In-Out Parameters:
As an optimization, when the argument is a value stored at a physical
address in memory, the same memory location is used both inside and
outside the function body. The optimized behavior is known as call by
reference; it satisfies all of the requirements of the copy-in
copy-out model while removing the overhead of copying. Do not depend
on the behavioral differences between copy-in copy-out and call by
reference.
If you have a function that takes a somewhat memory-wise large value type as argument (say, a large structure type) and that returns the same type, and finally where the function return is always used just to replace the caller argument, then inout is to prefer as associated function parameter.
Consider the example below, where comments describe why we would want to use inout over a regular type-in-return-type function here:
struct MyStruct {
private var myInt: Int = 1
// ... lots and lots of stored properties
mutating func increaseMyInt() {
myInt += 1
}
}
/* call to function _copies_ argument to function property 'myHugeStruct' (copy 1)
function property is mutated
function returns a copy of mutated property to caller (copy 2) */
func myFunc(var myHugeStruct: MyStruct) -> MyStruct {
myHugeStruct.increaseMyInt()
return myHugeStruct
}
/* call-by-reference, no value copy overhead due to inout opimization */
func myFuncWithLessCopyOverhead(inout myHugeStruct: MyStruct) {
myHugeStruct.increaseMyInt()
}
var a = MyStruct()
a = myFunc(a) // copy, copy: overhead
myFuncWithLessCopyOverhead(&a) // call by reference: no memory reallocation
Also, in the example above---disregarding memory issues---inout can be preferred simply as a good code practice of telling whomever read our code that we are mutating the function caller argument (implicitly shown by the ampersand & preceding the argument in the function call). The following summarises this quite neatly:
If you want a function to modify a parameter’s value, and you want
those changes to persist after the function call has ended, define
that parameter as an in-out parameter instead.
From Apple Language Guide: Functions - In-Out Parameters.
For details regarding inout and how it's actually handled in memory (name copy-in-copy-out is somewhat misleading...)---in additional to the links to the language guide above---see the following SO thread:
Using inout keyword: is the parameter passed-by-reference or by copy-in copy-out (/call by value result)
(Edit addition: An additional note)
The example given in the accepted answer by Lucas Huang above tries to---in the scope of the function using an inout argument---access the variables that were passed as the inout arguments. This is not recommended, and is explicitly warned not to do in the language ref:
Do not access the value that was passed as an in-out argument, even if
the original argument is available in the current scope. When the
function returns, your changes to the original are overwritten with
the value of the copy. Do not depend on the implementation of the
call-by-reference optimization to try to keep the changes from being
overwritten.
Now, the access in this case is "only" non-mutable, e.g. print(...), but all access like this should, by convention, be avoided.
At request from a commenter, I'll add an example to shine light upon why we shouldn't really do anything with "the value that was passed as an in-out argument".
struct MyStruct {
var myStructsIntProperty: Int = 1
mutating func myNotVeryThoughtThroughInoutFunction (inout myInt: Int) {
myStructsIntProperty += 1
/* What happens here? 'myInt' inout parameter is passed to this
function by argument 'myStructsIntProperty' from _this_ instance
of the MyStruct structure. Hence, we're trying to increase the
value of the inout argument. Since the swift docs describe inout
as a "call by reference" type as well as a "copy-in-copy-out"
method, this behaviour is somewhat undefined (at least avoidable).
After the function has been called: will the value of
myStructsIntProperty have been increased by 1 or 2? (answer: 1) */
myInt += 1
}
func myInoutFunction (inout myInt: Int) {
myInt += 1
}
}
var a = MyStruct()
print(a.myStructsIntProperty) // 1
a.myInoutFunction(&a.myStructsIntProperty)
print(a.myStructsIntProperty) // 2
a.myNotVeryThoughtThroughInoutFunction(&a.myStructsIntProperty)
print(a.myStructsIntProperty) // 3 or 4? prints 3.
So, in this case, the inout behaves as copy-in-copy-out (and not by reference). We summarize by repeating the following statement from the language ref docs:
Do not depend on the behavioral differences between copy-in copy-out
and call by reference.
Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake. If you want a function to modify a parameter’s value, and you want those changes to persist after the function call has ended, define that parameter as an in-out parameter instead.
inout param: modifies passing and local variable values.
func doubleInPlace(number: inout Int) {
number *= 2
print(number)
}
var myNum = 10 doubleInPlace(number: &myNum)
inout parameter allow us to change the data of a value type parameter and to keep changes still after the function call has finished.
If you work with classes then, as you say, you can modify the class because the parameter is a reference to the class. But this won't work when your parameter is a value type (https://docs.swift.org/swift-book/LanguageGuide/Functions.html - In-Out Parameters Section)
One good example of using inout is this one (defining math for CGPoints):
func + (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x + right.x, y: left.y + right.y)
}
func += (left: inout CGPoint, right: CGPoint) {
left = left + right
}
Basically it is useful when you want to play with addresses of variable its very useful in data structure algorithms
when use inout parameter swift 4.0 Work
class ViewController: UIViewController {
var total:Int = 100
override func viewDidLoad() {
super.viewDidLoad()
self.paramTotal(total1: &total)
}
func paramTotal(total1 :inout Int) {
total1 = 111
print("Total1 ==> \(total1)")
print("Total ==> \(total)")
}
}