Simplifying this Swift 4 logic - swift

Complete newb to Swift 4 here. How can the following be more compactly written in Swift?
if myVar != nil {
if !myVarList.contains(myVar!) {
myVarList.append(myVar!)
}
}
I tried searching for examples of guard but couldn't find anything. I think Swift allows me to more compactly deal with the nil checking, but not sure how to go about it when combined with the nested conditional.

Just use if let to conditional unwrap the optional and do the other check in the same line, the comma represents a boolean AND operator
if let item = myVar, !myVarList.contains(item) {
myVarList.append(item)
}
If an (unwrapped) optional is going to be used after the check never write != nil
guard is only useful if an evaluation to false exits the scope
func foo() {
guard let item = myVar, !myVarList.contains(item) else { return }
myVarList.append(item)
}

Related

I can't understand the swift language question mark operator in dictionary in this situation transitions[prev]?[transition] [duplicate]

This question already has answers here:
What is an optional value in Swift?
(15 answers)
When two optionals are assigned to an if let statement, which one gets unwrapped? Swift language
(1 answer)
Closed 5 years ago.
I've searched in a lot of places and communities among the internet to find what the heck is happening in this programing syntax.
I'm seeking, desperately, for guidance in this code.
What is happening with the compiler in these specific declarations?
transitions[prev]?[transition]
transitions[state]?[transition] != nil
This is how the class is declared
public final class StateMachine<State: Hashable, Transition: Hashable>
This is the variables
public var state: State
private var transitions = [State:[Transition:State]]()
And these are the examples:
First situation - What is happening in the transitions[prev]?[transition]
public final func advance(transition: Transition, observe: Observer? = nil) -> State {
let prev = state
if let next = transitions[prev]?[transition], next != prev {
state = next
observe?(prev, next)
}
return state
Second situation - What is happening in the return transitions[state]?[transition] != nil
public final func canAdvance(transition: Transition) -> Bool {
return transitions[state]?[transition] != nil
}
That's all i want to understand. What is happening in these moments?
The question mark operator signifies optionality in Swift.
You can declare many things a optional, meaning they could be nil or hold a value. This includes for example variable declarations, computed properties, return values of functions and callbacks/closures. Also certain operations like casting or retrieving values from dictionaries will yield optional values.
When you want to use the value contained you have to unwrap them, cause there might not be one and the may be pointing to nil. There are many ways and forms of unwrapping and optionality chaining.
Explaing your particular examples:
In a dictionary retrieving a stored value via a key as in myDict[myKey] returns an optional value. The value for the key stored within your specific dictionary is another dictionary. By declaring transitions[state]?[transition] you say basically "if there is a dictionary found for the key state, go ahead and continue with this dictionary and get the value for the key transition for that dictionary, otherwise use nil".
This code:
return transitions[state]?[transition] != nil
is basically a shorter way of writing this:
if let stateDict = transitions[state] {
return stateDict[transition] != nil
} else {
return false
}
Your other example is about an optional closure passed into a function. You can also pass optional closures into functions and call them via closure?(). The ? signifies that if nil is passed for the closure, nothing should be done, otherwise it should be executed.
This code:
observe?(prev, next)
is basically a shorter way of writing this:
if let observeClosure = observe {
observeClosure(prev, next)
}
Some more optionality explanations:
If you work with an optional value from a declared variable you can safely unwrap it like so:
func square(myValue: Int?) → Int {
guard let myValue = myValue else {
return 0
}
return myValue * myValue
}
or
func square(myValue: Int?) → Int {
if let myValue = myValue {
return myValue * myValue
} else {
return 0
}
}
or you could define a fallback with the ?? operator
func square(myValue: Int?) → Int {
return myValue ?? 0 * myValue ?? 0
}
You could also use the ! operator to unwrap unsafely and if nil is found your app would crash. You should never do that unless you can guarantee that nil cannot be found like in:
func square(myValue: Int?) → Int {
if myValue != nil {
myValue! * mayValue! {
} else {
return 0
}
}
In brief, transitions[state]?[transition] from time to time can be nil.
So, if let next = transitions[prev]?[transition] unwraps this variable moves the algorithm inside if-parenthesis
if let next = transitions[prev]?[transition] {
// this code executes here if 'transitions[prev]?[transition]' is not nil
state = next
observe?(prev, next) // this closure possibly can be nil. if nil Swift just skips this line
}

Why is a non-optional value printed as optional?

I've read Non-optional shown as optional on print but that doesn't help my question.
I'm returning a Integer, but once it's printing it's being printed as optional. Why?
I'm trying to solve a code challenge. The goal is to:
Write an extension for collections of integers that returns the number
of times a specific digit appears in any of its numbers.
Here is my implementation:
extension Collection where Iterator.Element == Int {
func challenge37(count character : Character) -> Int?{
guard nil != Int(String(character)) else{
print("character wasn't an integer")
return nil
}
var counts : [Int] = []
for item in self{
var counter = 0
let stringInt = String(describing: item)
for currentCharacter in stringInt.characters{
if character == currentCharacter{
counter += 1
}
}
counts.append(counter)
}
guard let min = counts.min() else{
print("no min")
return nil
}
return min
}
}
As you can see here I'm printing it:
print([5,15,512,522].challenge37(count: "5")) // Optional(1)
Inside the function your returning an Int. However the actual signature of your method is Int? meaning it is in fact an optional and you got it wrong!
Basically your method signature is correct. But when you call the function you're getting an optional as the response and must unwrap it.
print([5,15,512,522].challenge37(count: "5")!) // 1
Additionally had you paid close attention you would have noticed that Xcode must gave you a warning (and solutions to solve it)
Expression implicitly coerced from Int? to Any
Xcode gave you the warning because it found out that you're attempting to print an optional and knows that's usually unwanted. Obviously its solution is to unwrap it either through force unwrap or defaulting.

using guard to check for nil without implicitly unwrapping

I know there are some similar questions around, but I couldn't find one specific to my issue.
I have a request where I want to check for the presence of the error key. it is not present everything is fine, if not I should handle the error. Currently, I have it implemented as follows:
if let error = json["error"] {
// handle error
}
else {
// handle success
}
I would like to use a guard statement here to have the success case unindented. The only way I came up with is
guard json["error"] == nil else {
let error = json["error"]!
// handle error
}
// handle success
but that seems wrong to me with the !. Are there any other approaches to this?
In your guard code you would have to have a return statement in the else block. Like this...
guard json["error"] == nil else {
let error = json["error"]!
// handle error
return
}
// handle success
But you are correct. Having to force unwrap the error is not ideal.
So in this case. I think guard is the wrong solution. Instead use if but return from the conditional block. This removes the need for using an else block.
if let error = json["error"] {
print(error)
// handle error
return
}
// handle success...
// no need for else block. Just return from the if in the error case.
The difference between guard let and if let is where the unwrapped optional is scoped.
With guard it is scoped outside the block with if it is scoped inside the block.
An idea for your issue was proposed on the Swift Evolution mailing list:
"guard not let" optional binding
https://forums.swift.org/t/idea-guard-not-let-optional-binding/2614
[it is] fairly common that you want to check that an optional is nil, and still bail if it isn’t (maybe using the value that you now know exists), e.g:
guard cachedValue == nil else { return cachedValue! }
cachedValue = //… expensive calculation
It seems a little bit “unfair” that we have this lovely clean let syntax when checking for Optional.Some, but we to have to do this ugly manual check against nil and explicit unwrap when checking for Optional.None. There is literally no other way to satisfy the guard statement; our optional bindings only go one-way can’t be evaluated.
Unfortunately that construct does not currently exist in Swift.
The alternatives are the slightly awkward/duplicated guard syntax, possibly with a force-unwrap:
guard json["error"] == nil else {
return json["error"]!
}
or using if-let (which does not enforce scope-exit like guard):
if let error = json["error"] {
return error
}

Is there an operator in Swift that stops the evaluation of a multi expression conditional statement, as soon as the answer is clear?

In some programming language there is two other operator in addition with simple || and &&. these operators which I am going to call them _orif and _andif from now, can be used in place of && and || and They may help to improve efficiency and avoid errors, because evaluation of the conditional stops as soon as the answer is clear.
For example, evaluation of the following expression will stop halfway through (selectedSprite != nil) is false: So the rest of the conditional will be ignored and never evaluated, this will prevent a fatal error in this case : fatal error: unexpectedly found nil while unwrapping an Optional value and it will raise while reaches to the second expression because obviously nil does not responds to SpriteOwner().
if (selectedSprite != nil) &&
(selectedSprite.SpriteOwner().type == "Human")
{
println("a human selected")
}
I am looking for a replacement for && in above piece of code that could be used instead of the simple && operator, So if the first expression is evaluated as a false one (having the selectedSprite equal to nil) then the second expression be ignored at all.(since it does not have any influence on result)
Question:
Is there such a &&? operator in swift? if the answer is a No,
Is there a better way of doing that instead of nested if statements like I have written here :
if (selectedSprite != nil)
{
if (selectedSprite.SpriteOwner().type == "Human")
{
println("a human selected")
}
}
I am implementing an intelligent system with a lot of if clause in it and most of them are too complicated which adding a new if layer just to control nils is a real nightmare.
What you described is called short circuiting and Swift does have it. For example:
let a : Int? = nil
if a != nil && a! == 1 {
print("a is 1")
} else {
print("a is nil")
}
You can see a is never unwrapped. I think in your case, it's more likely that SpriteOwner() returns nil. the Swifty way to unwrap optional values is to use the let ... where ... syntax:
if let s = selectedSprite where s.SpriteOwner().type == "Human" {
println("a human selected")
}
The binary logical || and && operators in Swift 2 already behave as you describe. See "The Swift Programming Language", under "Logical AND Operator" : https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID60
If either value is false, the overall expression will also be false. In fact, if the first value is false, the second value won’t even be evaluated, because it can’t possibly make the overall expression equate to true. This is known as short-circuit evaluation.
Try executing the following in a playground; you will see that the second part of the conditional statement is never executed since the first part is false:
func isBar(rv: Bool) -> Bool {
print("side effect of isBar")
return rv
}
func isFoo() -> Bool {
print("side effect of isFoo")
return true
}
if isBar(false) && isFoo() {
print("both true")
}
You could achieve something similar with optional chaining:
class Sprite {
let otherSprite: Sprite?
let type: String
init(otherSprite: Sprite?, type: String) {
self.otherSprite = otherSprite
self.type = type
}
}
let innerSprite = Sprite(otherSprite: nil, type: "Human")
let outerSprite = Sprite(otherSprite: innerSprite, type: "Robot")
This doesn't execute the print statement because they otherSprite? comes back with a nil
if innerSprite.otherSprite?.type == "Human" {
print("A human selected")
}
This will print "A human selected" because the value of otherSprite is non-nil and the type's value == "Human"
if outerSprite.otherSprite?.type == "Human" {
print("A human selected")
}

swift, optional unwrapping, reversing if condition

Let's say I have function which returns optional. nil if error and value if success:
func foo() -> Bar? { ... }
I can use following code to work with this function:
let fooResultOpt = foo()
if let fooResult = fooResultOpt {
// continue correct operations here
} else {
// handle error
}
However there are few problems with this approach for any non-trivial code:
Error handling performed in the end and it's easy to miss something. It's much better, when error handling code follows function call.
Correct operations code is indented by one level. If we have another function to call, we have to indent one more time.
With C one usually could write something like this:
Bar *fooResult = foo();
if (fooResult == null) {
// handle error and return
}
// continue correct operations here
I found two ways to achieve similar code style with Swift, but I don't like either.
let fooResultOpt = foo()
if fooResult == nil {
// handle error and return
}
// use fooResultOpt! from here
let fooResult = fooResultOpt! // or define another variable
If I'll write "!" everywhere, it just looks bad for my taste. I could introduce another variable, but that doesn't look good either. Ideally I would like to see the following:
if !let fooResult = foo() {
// handle error and return
}
// fooResult has Bar type and can be used in the top level
Did I miss something in the specification or is there some another way to write good looking Swift code?
Your assumptions are correct—there isn't a "negated if-let" syntax in Swift.
I suspect one reason for that might be grammar integrity. Throughout Swift (and commonly in other C-inspired languages), if you have a statement that can bind local symbols (i.e. name new variables and give them values) and that can have a block body (e.g. if, while, for), those bindings are scoped to said block. Letting a block statement bind symbols to its enclosing scope instead would be inconsistent.
It's still a reasonable thing to think about, though — I'd recommend filing a bug and seeing what Apple does about it.
This is what pattern matching is all about, and is the tool meant for this job:
let x: String? = "Yes"
switch x {
case .Some(let value):
println("I have a value: \(value)")
case .None:
println("I'm empty")
}
The if-let form is just a convenience for when you don't need both legs.
If what you are writing is a set of functions performing the same sequence of transformation, such as when processing a result returned by a REST call (check for response not nil, check status, check for app/server error, parse response, etc.), what I would do is create a pipeline that at each steps transforms the input data, and at the end returns either nil or a transformed result of a certain type.
I chose the >>> custom operator, that visually indicates the data flow, but of course feel free to choose your own:
infix operator >>> { associativity left }
func >>> <T, V> (params: T?, next: T -> V?) -> V? {
if let params = params {
return next(params)
}
return nil
}
The operator is a function that receives as input a value of a certain type, and a closure that transforms the value into a value of another type. If the value is not nil, the function invokes the closure, passing the value, and returns its return value. If the value is nil, then the operator returns nil.
An example is probably needed, so let's suppose I have an array of integers, and I want to perform the following operations in sequence:
sum all elements of the array
calculate the power of 2
divide by 5 and return the integer part and the remainder
sum the above 2 numbers together
These are the 4 functions:
func sumArray(array: [Int]?) -> Int? {
if let array = array {
return array.reduce(0, combine: +)
}
return nil
}
func powerOf2(num: Int?) -> Int? {
if let num = num {
return num * num
}
return nil
}
func module5(num: Int?) -> (Int, Int)? {
if let num = num {
return (num / 5, num % 5)
}
return nil
}
func sum(params: (num1: Int, num2: Int)?) -> Int? {
if let params = params {
return params.num1 + params.num2
}
return nil
}
and this is how I would use:
let res: Int? = [1, 2, 3] >>> sumArray >>> powerOf2 >>> module5 >>> sum
The result of this expression is either nil or a value of the type as defined in the last function of the pipeline, which in the above example is an Int.
If you need to do better error handling, you can define an enum like this:
enum Result<T> {
case Value(T)
case Error(MyErrorType)
}
and replace all optionals in the above functions with Result<T>, returning Result.Error() instead of nil.
I've found a way that looks better than alternatives, but it uses language features in unrecommended way.
Example using code from the question:
let fooResult: Bar! = foo();
if fooResult == nil {
// handle error and return
}
// continue correct operations here
fooResult might be used as normal variable and it's not needed to use "?" or "!" suffixes.
Apple documentation says:
Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. The primary use of implicitly unwrapped optionals in Swift is during class initialization, as described in Unowned References and Implicitly Unwrapped Optional Properties.
How about the following:
func foo(i:Int) ->Int? {
switch i {
case 0: return 0
case 1: return 1
default: return nil
}
}
var error:Int {
println("Error")
return 99
}
for i in 0...2 {
var bob:Int = foo(i) ?? error
println("\(i) produces \(bob)")
}
Results in the following output:
0 produces 0
1 produces 1
Error
2 produces 99