Why does my code work on Playgrounds but not CoderPad? - swift

I have a very simple func in Xcode playgrounds which works when I run it. But when i try to run the same code in CoderPad it gives me the following error Solution.swift:18:1: warning: result of call to 'isPalindrome(word:)' is unused
isPalindrome(word:"racecar")
Here is the code
import Foundation
func isPalindrome(word: String) -> Bool{
var oddCharacters: Set<Character> = []
for char in word {
if oddCharacters.contains(char){
oddCharacters.remove(char)
}else{
oddCharacters.insert(char)
}
}
return oddCharacters.count <= 1
}
isPalindrome(word:"racecar")
I really do not understand why this is happening.

Try this:
import Foundation
func isPalindrome(word: String) -> Bool{
var oddCharacters: Set<Character> = []
for char in word {
if oddCharacters.contains(char){
oddCharacters.remove(char)
}else{
oddCharacters.insert(char)
}
}
return oddCharacters.count <= 1
}
print(isPalindrome(word:"racecar"))
all you had to do was print it, hope this helped

That means, that the "left-hand-side" result of the call to your function isPalindrome(word: "racecar") is unused ("wasted").
It seems that for a debugging, testing, try-out environment like a Playground it's just okay to find out the result of this call (true) without storing it inside a variable. However, when doing that in other development environments, the compiler will be complaining about that. I can give you four options that would prevent the error from being thrown, just to give you a better idea of why the compiler is complaining:
If you want to use it in your further code below, just store the result and change your calling line to let isPalindrome = isPalindrome(word: "racecar"). But if you don't use it, the compiler will give you a warning again saying that you're never using your isPalindrome variable... --> Option 2
If you don't need the result, you can also just say: _ = isPalindrome(word: "racecar"). That will explicitly tell the compiler "bro, it's okay if the result is just ignored". It wouldn't make much sense for this function, though.
You can add the #discardableResult keyword prior to your function declaration, so it would say: #discardableResult func isPalindrome(word: String) -> Bool { ... That would kinda just silence your thrown error and like option 2 just tell the compiler that it's okay to just ignore the result of this function.
Just use the result in any way like:
if isPalindrome(word: "racecar") {
// do something
} else {
// do something else
}
// or
print("racecar is a palindrome: \(isPalindrome(word: "racecar")")
and everything will just be fine. I hope that helps you!

Related

Guard with trailing closure - Swift Syntax

Let's say, I have a function which takes a closure as its last parameter, so it can be shortened to something like this:
let reminder = reminders.first { (reminder) -> Bool in
return reminder.mealIdentifier == mealIdentifier
}
Awesome! Now let's say I want to put this in a guard statement, like this:
guard let reminder = reminders.first { (reminder) -> Bool in
return reminder.mealIdentifier == mealIdentifier
} else {
continue
}
The moment I do this, the compiler starts screaming. The fix is to use no trailing closure short syntax when calling the function, but it's cumbersome as the default auto-completion by Xcode doesn't have an option to NOT do trailing closures short syntaxes when your last parameter is a closure:
guard let reminder = reminders.first(where: { (reminder) -> Bool in
return reminder.mealIdentifier == mealIdentifier
}) else {
continue
}
Is there anything I'm missing here? Or is there a way to somehow have Xcode do autocompletion without the shortened syntax?
Or is there a way to somehow have Xcode do autocompletion without the shortened syntax?
Xcode is quite smart. It chooses the non-trailing closure version if you do the auto completion in a control flow statement that needs a {. For example, if I type:
guard let a = reminders.first
The auto complete shows:
If I choose the highlighted option, I get:
guard let a = reminders.first(where: <#T##(String) throws -> Bool#>)
If I then press enter, I get:
guard let a = reminders.first(where: { (<#String#>) -> Bool in
<#code#>
})
It doesn't turn it into a trailing closure, as long as you autocomplete within a guard/if statement.

How can you mark a method that it is fatal, like `fatalError`?

We have a special logging function that represents a particular type of crash, and as such, internally it calls fatalError. However, unlike fatalError, when we use it in a guard statement, it still complains we haven't exited the scope of the guard.
I checked the source code and fatalError returns -> Never so I tried that, but that didn't work either. I also didn't see any attributes applied to it that may be telling the compiler 'this is the end of the road'.
So is it possible to have your own fatalError-like method?
func myFatalError(memberName:String = #function) -> Never {
let message = "Failed in \(memberName)"
NSLog(message)
fatalError(message)
}
As pointed out by others, the issue was something on my machine specifically. The following (returning 'Never') works as expected.
func myFatalError() -> Never {
print("Doing something fatal")
}

How do I rewrote this peace of code in swift 2

I am trying to make my first app and I am stuck. I don't know how to rewrite this piece of code from an earlier version of Swift in Swift 2.
func rowCheck(value value:Int) -> (location :String,pattern :String)?{
let acceptableFinds = ["101","110","011"]
var findFunc = [checkGornjiR,checkSrednjiR,checkDonjiR,checkLevuK,checkSrednjuK,checkDesnuK,checkLevuD,checkDesnuD]
for algorithm in findFunc{
let algorithmResults = algorithm(value:value)
if find(acceptableFinds,algorithmResults.pattern) { // Error on this line
return algorithmResults
}
}
return nil
In "if" line I am getting error:
"Optional type 'C.index?' cannot be used as a boolean; test for '!=nil' instead
A bit of help would be nice! Thanks!
you van use contains which return Bool value like this:
if acceptableFinds.contains(algorithmResults.pattern) {

Why doesn't this base type extension work?

Trying to play with extensions, but am having issues getting the following to work:
let value = -13
abs(value)
extension Int {
var abs:Int {
return abs(self) // -> Cannot invoke 'abs' with an argument list of type '(Int)'
}
}
value.abs
The compile error is weird, because it demonstrably runs the abs() function directly above with an Int as an argument. I've still got some light bulbs to trigger for generics I guess. Enlighten me.
The Swift compiler is confused that you use the abs variable as a function, which it cannot do. Now you could look at all the answers and rename your variable, but these do not give insight in how Swift functions work.
Swift automatically imports the Swift framework, where it defines its static functions. To use these functions, you usually do not need to specify that it's from the framework, but in cases like this, you should specify that you want to use the abs method from the Swift framework.
So after all the explanation, here's your code, which will work:
let value = -13
abs(value)
extension Int {
var abs: Int {
return Swift.abs(self)
}
}
value.abs
It appears just a call resolution problem. This will work:
let value = -13
abs(value)
extension Int {
var abs1:Int {
return abs(self)
}
}
value.abs1
And this will work too:
extension Int {
var abs:Int {
return self < 0 ? -self : self
}
}
value.abs
The problem here is that you are extending Int to add a variable named abs -- which is also the name of the function you are calling.
When you try to call the function abs() on the Int, it sees the variable abs that you created and it is confused because it thinks you are trying to return that variable and doesn't understand why you are sending it a parameter.
If you rename your variable to absoluteValue or anything else really, it should work.
let value = -13
abs(value)
extension Int {
var absoluteValue:Int {
return abs(self)
}
}
value.abs
Update: As others have stated, you can also solve the disambiguation of the use of abs by explicitly calling the function within the Swift framework. This should work just as well as the above solution.
let value = -13
abs(value)
extension Int {
var abs:Int {
return Swift.abs(self)
}
}
value.abs
Though, personally, I would still rename my new function to absoluteValue as in the first example so that its clear that you aren't calling the Swift.abs() when you use your abs variable.
Thanks to the direction of the original two answers (clash between global free function and the var I was defining), they have to be disambiguated. Rather than do my own inline implementation of abs or be forced to use a different name, I can properly scope the inside abs() using the Swift namespace.
extension Int {
var absoluteValue:Int {
return Swift.abs(self)
}
}
This gives me the best of both worlds (IMO).

Swift closure problems [duplicate]

I am moving my code from Obj. C to Swift C and trying to implementing the Twitter sdk..
But, I am getting an error...
Can any body tell me what I have done wrong.
Please help me with this.
I spent 2 days tried everything but didn't work for me.
Your block does not have a return statement, therefore the compiler
uses the result of the last statement
UIApplication.sharedApplication().openURL(url)
as return value, which is a Bool and not Void as declared in the block signature.
To solve that problem, just add a return statement:
{ (url: NSURL, oauthToken: String) -> Void in
UIApplication.sharedApplication().openURL(url)
return
}
The problem is that openURL returns a boolean, and an attempt to convert it to Void is made, since the closure is declared as returning a Void. Simply remove that as follows:
{ (url: NSURL, token: String) in
UIApplication.sharedApplication().openURL(url)
}
If you don't want to change the closure signature, just assign the return value to a variable:
{ (url: NSURL, token: String) -> Void in
let ret = UIApplication.sharedApplication().openURL(url)
}
What's not stated in the other answers is that Swift will implicitly add a return to a single statement closure.
This is how statements like conditionSet.sort {$0.set < $1.set} can work.
This can also result in an unexpected error. To avoid the error, make the closure have 2 statements. The simplest way is to add a return after your original statement as stated in the accepted answer.