I have four functions which I want to activate randomly. This is the code I have so far, which I get no errors from. However, I get an error "Expression Resolves to an unused function" when I try to call the createSquare() function.
func createSquare () -> () -> () {
let squares = [self.squareOne, self.squareTwo, self.squareThree, self.squareFour]
let randomSquare = Int(arc4random_uniform(UInt32(squares.count)))
return squares[randomSquare]
}
if gameIsOn == true {
createSquare()
}
How can I successfully call the function createSquare()?
func squareOne() {
square1.isHidden = false
}
And squareTwo, squareThree, squareFour are all similar with different numbers.
The problem is that createSquare() returns a closure that you never invoke (that's the "unused function" mentioned in the warning message).
You need to call the function, for example, like this:
let randomFunction = createSquare()
randomFunction()
You can also call it right away with a somewhat less readable syntax:
createSquare()()
func createSquare() {
let randomNumber = Int.random(in: 0...3)
if randomNumber == 0 {
squareOne()
} else if randomNumber == 1 {
squareTwo()
} else if randomNumber == 2 {
squareThree()
} else if randomNumber == 3 {
squareFour()
}
}
Related
How do i get the result of of i to return from the function here? I can return it from inside the if { } but then I get an error there’s no global return (for the function). My goal is to write a function that accepts an Integer and returns the square root. My next step is to throw an error if it's not an Int or between 1 and 10,000, but please assume simple numbers for this question.
let userInputInteger = 9
func squareRootCheckpoint4(userInputInteger: Int) -> Int {
for i in 1...100 {
let userInputInteger = i * i
if i == userInputInteger {
break
}
}
return i
}
update:
To be able to return it, you will have to declared a variable outside the for-loop, then based on the logic assign the "i" counter to that outside variable.
func squareRootCheckpoint4(userInputInteger: Int) -> Int {
var result = 0 // this is to keep the result
for i in 1...100 {
let powerOfTwoResult = i * i
if powerOfTwoResult == userInputInteger {
result = i // assign result variable based on the logic
break
}
}
return result // return result
}
The error shown is because if the for-loop finishes without any hit on the if statement, the function will not be able to return any Int. That's why the compiler produces that "no global return" error.
One way to do it if you don't want to return a default value is to throw an error. You could throw an error from a function (https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html). For example for your goal of returning square root of an integer and throw error if the input integer is not between 1 and 10000 (if I understand correctly), you could do something like this
enum InputError: Error {
case invalidInteger
}
func squareRootCheckpoint4(userInputInteger: Int) throws -> Int {
if userInputInteger < 1 || userInputInteger > 10000 {
throw InputError.invalidInteger
}
// calculate square root
return resultOfSquareroot
}
// and to handle the error, you could encapsulate the squareRootCheckpoint4 function in a do-catch statement
do {
let squareRootResult = try squareRootCheckpoint4(userInputInteger: 4)
} catch InputError.invalidInteger {
// handle your error here
}
Alternatively, you could do a validation on the input integer separately before calling the squareRootCheckpoint4 function. For example
func validate(_ input: Int) -> Bool {
if userInputInteger < 1 || userInputInteger > 10000 {
return false
}
return true
}
func squareRootCheckpoint4(userInputInteger: Int) -> Int {
// calculate square root
return resultOfSquareroot
}
var input: Int = 9
if validate(input) {
let squareRootResult = squareRootCheckpoint4(input)
} else {
// handle when input is invalid
}
A couple of things are swapped around, and something (anything) needs to be returned from the function. The framing of the question only allows solutions that don't work if the input is not an integer with a square root.
List of Specifics:
The function argument name userInputInteger should not have been used to instantiate a new object. That's confusing. I did it because I'm learning and thought it was necessary.
Instead, i times i (or i squared) should have been assigned to a new object.
The if statement should be equal to this new object, instead of i.
Functions should return something. When i is returned in the if statement, it's not available anywhere outside the for loop. The print statements in the code example help explain what is available in these different scopes, as well as what's not.
The for loop stops when i is returned. That happens when the guess (i) is equal to the input (userInputInteger).
The for loop will continue through 100 if the input doesn't have a square root.
The function should return the correct number that the if statement was trying to guess, but you have to tell it to (with a return statement) and do it in the right spot. This is the "global return" error. However, because this approach in the question is setup poorly without error handling, only an Integer with a sqare root will return correctly. And in this case, the function's global return doesn't matter; Swift just requires something be returned, regardless of whether or not it's used.
Code Example - Direct Answer:
import Cocoa
let userInputInteger = 25
let doesNotMatter = 0
print("sqrt(\(userInputInteger)) is \(sqrt(25))") //correct answer for reference
func squareRootCheckpoint4(userInputInteger2: Int) -> Int {
var j: Int
for i in 1...100 {
print("Starting Loop \(i)")
j = i * i
if j == userInputInteger2 {
print("i if-loop \(i)")
print("j if-loop \(j)")
return i
}
print("i for-loop \(i)")
print("j for-loop \(j)")
}
//print("i func-end \(i)") //not in scope
//print("j func-end \(j)") //not in scope
//return i //not in scope
//return j //not in scope
print("Nothing prints here")
// but something must be returned here
return doesNotMatter
}
print("Input was \(userInputInteger)")
print("The Square Root of \(userInputInteger) is \(squareRootCheckpoint4(userInputInteger2: userInputInteger))")
Code Example - Improved with Error Handling
import Cocoa
enum ErrorMsg : Error {
case outOfBoundsError, noRootError
}
func checkSquareRoot (Input userInputInteger2: Int) throws -> Int {
if userInputInteger < 1 || userInputInteger > 10_000 {
throw ErrorMsg.outOfBoundsError
}
var j : Int
for i in 1...100 {
print("Starting Loop \(i)")
j = i * i
if j == userInputInteger2 {
print("i if-loop \(i)")
print("j if-loop \(j)")
return i
}
print("i for-loop \(i)")
print("j for-loop \(j)")
}
throw ErrorMsg.noRootError
}
let userInputInteger = 25
print("Input was \(userInputInteger)")
do {
let result = try checkSquareRoot(Input: userInputInteger)
print("The Square Root of \(userInputInteger) is \(result)")
} catch ErrorMsg.outOfBoundsError {
print("out of bounds: the userInputInteger is less than 1 or greater than 10,000")
} catch ErrorMsg.noRootError {
print("no root")
}
print("Swift built-in function for reference: sqrt(\(userInputInteger)) is \(sqrt(25))") //correct answer for reference
I know that closures capture the values in a given environment. That is not my question. My question is how do I capture the return value of a closure. For example if I use a closure as a parameter like:
func myClosure(yourAge x: Int, completion: (Int) -> String) {
if x == 4 {
completion(x)
}
}
then say:
let answer = myClosure(yourAge: 4) { x in
return "You're just a baby"
}
The warning is:
Constant 'answer' inferred to have type '()', which may be unexpected
And I understand that warning. Pretty much answer will not be an answer at all. It will be Void or ()
Now if I make the entire function return a String such as:
func myClosure(yourAge x: Int, completion: (Int) -> String) -> String {
completion(x)
}
Then I can of course capture the result in a property:
let answer = myClosure(yourAge: 4) { x in
if x < 10 { return "You're just a baby"}
else {
return "You can play the game"
}
}
And maybe I just answered my own question here but is there no simple way to place the return value of a closure into a property or I am using this in an unintended way?
If you wanted to do this purely with a closure (and not a function that accepts a closure), you could do something like:
let myClosure: (Int) -> String = { age in
if age < 10 {
return "You're just a baby"
}
else {
return "You can play the game"
}
}
let answer = myClosure(4) // "You're just a baby"
This is a question that aims merely at elegance, but is there a way to make something to the following code work in Swift? I know the code does not work, what I want is that the result of the code within the closure is stored in a constant. And the underlying theoretical issue is whether or not it is possible to retrieve the returned value from the closure with type Int and not with type () -> Int.
Thanks a lot for any help or comment!
let tableWithBooleans: [Bool] = Array(repeating: false, count: 10)
tableWithBooleans[0] = true
tableWithBooleans[5] = true
let numberOfTrue: Int = {
var result: Int = 0
for i in 0...9 {
if tableWithBooleans[i] {
result += 1
}
}
return result
}
// I want the code to compile and numberOfTrue to be a constant equal to 2
Use a high-order function instead
let numberOfTrue = tableWithBooleans.reduce(0) { $1 ? $0 + 1 : $0 }
Now if you still want to use your closure code then you should add a () after the closing } since you are calling the code inside {} as a function
let numberOfTrue: Int = {
var result: Int = 0
for i in 0...9 {
if tableWithBooleans[i] {
result += 1
}
}
return result
}()
Please consider the following:
func example(array: [Int]) {
guard array.count > 0 else { return }
// Do something
}
It would be nice to announce the restriction via the function signature. Is it possible to constrain the parameter? Something equivalent to:
func example(array: [Int] where array.count > 0) {
// Do something
}
Going one step further: let's make the array optional:
func example(array: [Int]?) {
guard array == nil || array!.count > 0 else { return }
// Do something
}
func example(array: [Int]? where array.count > 0) {
// Do something
}
No, you can't have a conditional parameter. The best you can do is what you have in the second option with an optional and before you call the function (or posibly in the function) check if it is nil.
This link tells you what your sorting function has to look like, but I just can't make a Swift function look like that.
Here's my call:
packetsArray.sortUsingFunction(comparePacketDates, context: nil)
Here's my function, and I've tried a zillion other variations of it:
static func comparePacketDates(packet1 : AnyObject, packet2: AnyObject, context: UnsafeMutablePointer<Void>) -> Int {
And I've tried using a c function instead, this and a few other variations:
NSInteger comparePacketDates(id packet1, id packet2, void* dummy);
It's always "cannot invoke with argument list ..." saying the function isn't what's expected as the first argument.
Does anyone have example code of a Swift function that would be accepted as the first argument of the Swift sortUsingFunction? Or even a c function that would be accepted as the first argument of the Swift SortUsingFunction?
Use sortUsingComparator. It's simpler than sortUsingFunction. Here's the syntax:
a.sortUsingComparator {
let packet1 = $0 as! Packet
let packet2 = $1 as! Packet
if packet1.timestamp < packet2.timestamp {
return .OrderedAscending
}
if packet1.timestamp == packet2.timestamp {
return .OrderedSame
}
return .OrderedDescending
}
Here is an example for your reference that I wrote:
var ma = NSMutableArray()
ma.addObject("Hi")
ma.addObject("Anil")
func comp(first: AnyObject, second:AnyObject, context: UnsafeMutablePointer<Void>) -> Int {
let f:String = first as! String
let s:String = second as! String
if f > s {
return 1
}
else if ( f == s ) {
return 0
}
return -1
}
ma.sortUsingFunction(comp, context:UnsafeMutablePointer<Void>(bitPattern: 0))
HTH, as a reference to you. Note: I am in Xcode 7.1 Swift 2.1.