Optional properties in optional classes VS Optional values in optional dictionaries - ios

I noticed some interesting behavior when trying to access values of optional properties in optional classes VS trying to access the values of optional values in optional dictionaires.
It seems that in the former case you only need to unwrap once to access the value. However, in the latter case you have to unwrap twice to access the value. I was wondering why this is, and was hoping someone could provide me with some insight!
Below is an example accessing the value of an optional property in an optional class
class Cat{
var food : Food?
}
class Food{
var amount : Int?
}
var meowzer = Cat()
meowzer.food = Food()
meowzer.food?.amount = 10
var catFoodAmt = meowzer.food?.amount
print("\(catFoodAmt)")
if let catFoodCount = meowzer.food?.amount{
print("\(catFoodCount)")
}
The result of the first print statement is:
Optional(10)
The result of the second print statement (after unwrapping) is:
10
Below is an example of accessing the value of an optional value in an optional dictionary
var dog : [String : Int?]?
dog = ["treat_count" : 10]
var dogTreatAmt = dog?["treat_count"]
print("\(dogTreatAmt)")
if let dogTreatCount = dog?["treat_count"] , dogTreatCountFinal = dogTreatCount{
print("\(dogTreatCount)")
print("\(dogTreatCountFinal)")
}
The result of the first print statement is:
Optional(Optional(10))
The result of the second print statement (after unwrapping once) is:
Optional(10)
The result of the third print statement (after unwrapping twice) is:
10
Why do I need to unwrap twice to access the desired value in the second case but not the first?
My guess is it has to do with that fact that if I were to have used a key other than "treat_count" (like "count" for example) then the value for that key would have been nil. However, I haven't been able to find a iOS "rule" or a better explanation on why this is. Any help would be much appreciated.

The difference is that Cat.food?.amount returns Int? while Dictionary<String, Int?>.subscript(String) returns Int??.
This is because Dictionary.subscript<Key> returns Element?, and Element here is Int?. Thus you're getting one extra level of Optional.
Optional chaining just removes an extra Optional wrapping at the point that it's used. It doesn't collapse all Optionals. In one case you have two, collapsed to 1 (for one ?) and in the second you have three, collapsed to 2 (for one ?).
As vadian suggests, this would be a crazy Dictionary, so it's unlikely to come up in good Swift, but it can be reasoned about. If it weren't like this, you would lose information.

It actually makes sense : simply count the number of ?s :).
With you first example, the property is an optional where, in your second example, you have an optional dictionary where its key is a string and the value is an optional integer.
So if you want to access the value of the second example, you have to unwrap the dictionary, then unwrap whatever there is in that dictionary for a given key.

This is a good question. Let's think the type definition of a Dictionary:
struct Dictionary<Key : Hashable, Value>
And the signature of the subscript function:
public subscript (key: Key) -> Value?
Which can also be thought of as:
public subscript (key: Key) -> Optional<Value>
Armed with this, let's look at your dictionary, which is typed as:
Dictionary<String, Int?>
Or more explicitly
Dictionary<String, Optional<Int>>
Where Value is of type Optional<Int>, and Key is of type String
So if we substitute in the key, the subscript definition is:
subscript (key: String) -> Optional<Value>
And if we substitute it in the Value, we get what you are seeing:
subscript (key: String) -> Optional<Optional<Int>
Now, let's break down your code and to make everything fit together:
var dogTreatAmt = dog?["treat_count"]
Since dog is optional, no matter what you call on it, the result will also be wrapped in an Optional, which we will temporarily think of as Optional(FunctionReturn)
Now let's take a look at FunctionReturn, which is the subscript function. We have already determined that this will return Optional<Optional<Int>>
Which means that really you're returning Optional<Optional<Optional<Int>>>, however as noted by Rob Napier,
"Optional chaining removes an extra Optional wrapping at the point that it's used".

Related

confused about the null safety dart

The argument type 'int?' can't be assigned to the parameter type 'num'.
when using darts with 'null safety', this code gets an error but when I use the version of darts without null safety the test runs successfully (without error). My question is how do I change this code so that it doesn't error on darts with null safety?
If you take a look at the documentation of the [] operator on Map:
V? operator [](
Object? key
)
V? here means that the type of the value V will always be nullable. The reason for this is because of the following detail for this operator:
The value for the given key, or null if key is not in the map.
https://api.dart.dev/stable/2.18.1/dart-core/Map/operator_get.html
So the reason for your error is because your code is not prepared for the case of [] returns null in case the key are not in your Map.
There are multiple solutions for this problem which depends on how sure you are about the specific piece of code and what behavior you want in case of failure.
If you are e.g. completely sure that curr will always point to a valid key in the Map you can do: scarScore[curr]! (notice the !). This will add a runtime null-check and crash your application in case the value from the [] operator ends up being null.
Alternative, if you expect some keys to not be in the Map, you can provide default values like prev + (scarScore[curr] ?? 0) where null will then be assumed to be translated to the value 0.
For a detailed explanation for why the [] operator are nullable, you can read: https://dart.dev/null-safety/understanding-null-safety#the-map-index-operator-is-nullable

How to cast `Int8?` to `Int?`?

I have a UInt8? variable named seconds that I need to pass to a function accepting Int?.
This leads to Cannot convert value of type UInt8? to expected argument type Int?.
This means I have to cast, and so I tried the obvious:
Int?(seconds)
But this results in: UInt8? is not convertible to Int.
Of course I could do:
(seconds == nil) ? nil : Int(seconds!)
But WTF, does it really have to be so contrived?
Your type is Optional<UInt8>. A UInt8 can always be converted to an Int with the function Int.init. But since it's wrapped in an Optional, you'll have to map that function over the optional, yielding a new value of type Optional<Int>:
seconds.map(Int.init)
Optional.map(_:) and its companion flatMap often make working with optionals a lot easier.

Implicitly unwrapped optional assign in Xcode 8

In Xcode 8 release version, i found a strange scene.
Here is the code,
let implicitlyUnwrappedOptionalString: String! = "implicitlyUnwrappedOptionalString"
let foo = implicitlyUnwrappedOptionalString
print(implicitlyUnwrappedOptionalString)
print(foo)
and here is the result:
implicitlyUnwrappedOptionalString
Optional("implicitlyUnwrappedOptionalString")
These above shows that when i assign a implicitly unwrapped optional to a variable without a explicit type, the type will be inferred to an optional type, not the type which it originally is, aka implicitly unwrapped optional.
My Xcode has been updated to 8. Anyone can verify the behavior in Xcode 7.x?
The change is due to the Swift version changing or the Xcode?
This is a consequence of SE-0054 Abolish ImplicitlyUnwrappedOptional type which has been implemented in Swift 3. Extract from that proposal (emphasis added):
However, the appearance of ! at the end of a property or variable declaration's type no longer indicates that the declaration has IUO type; rather, it indicates that (1) the declaration has optional type, and (2) the declaration has an attribute indicating that its value may be implicitly forced. ...
If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary. The effect of this behavior is that the result of any expression that refers to a value declared as T! will either have type T or type T?. For example, in the following code:
let x: Int! = 5
let y = x
let z = x + 0
… x is declared as an IUO, but because the initializer for y type checks correctly as an optional, y will be bound as type Int?. However, the initializer for z does not type check with x declared as an optional (there's no overload of + that takes an optional), so the compiler forces the optional and type checks the initializer as Int.
In your case, the assignment
let foo = implicitlyUnwrappedOptionalString
makes foo a strong optional, as in the example let y = x
from the proposal.
You could make foo an IUO by adding an explicit type annotation
let foo: String! = implicitlyUnwrappedOptionalString
but generally you should try to get rid from IUOs in your code,
as stated in the same proposal:
Except for a few specific scenarios, optionals are always the safer bet, and we’d like to encourage people to use them instead of IUOs.

Good behavior for subscript

I'm creating an extension for String and I'm trying to decide what proper/expected/good behavior would be for a subscript operator. Currently, I have this:
// Will crash on 0 length strings
subscript(kIndex: Int) -> Character {
var index = kIndex
index = index < 0 ? 0 : index
index = index >= self.length ? self.length-1 : index
let i = self.startIndex.advancedBy(index)
return self.characters[i]
}
This causes all values outside the range of the string to be capped to the edge of the string. While this reduces crashing from passing a bad index to the subscript, it doesn't feel like the right thing to do. I am unable to throw an exception from a subscript and not checking the subscript causes a BAD_INSTRUCTION error if the index is out of bounds. The only other option I can think of is to return an optional, but that seems awkward. Weighing the options, what I have seems to be the most reasonable, but I don't think anybody using this would expect a bad index to return a valid result.
So, my question is: what is the "standard" expected behavior of the subscript operator and is returning a valid element from an invalid index acceptable/appropriate? Thanks.
If you're implementing a subscript on String, you might want to first think about why the standard library chooses not to.
When you call self.startIndex.advancedBy(index), you're effectively writing something like this:
var i = self.startIndex
while i < index { i = i.successor() }
This occurs because String.CharacterView.Index is not a random-access index type. See docs on advancedBy. String indices aren't random-access because each Character in a string may be any number of bytes in the string's underlying storage — you can't just get character n by jumping n * characterSize into the storage like you can with a C string.
So, if one were to use your subscript operator to iterate through the characters in a string:
for i in 0..<string.characters.count {
doSomethingWith(string[i])
}
... you'd have a loop that looks like it runs in linear time, because it looks just like an array iteration — each pass through the loop should take the same amount of time, because each one just increments i and uses a constant-time access to get string[i], right? Nope. The advancedBy call in first pass through the loop calls successor once, the next calls it twice, and so on... if your string has n characters, the last pass through the loop calls successor n times (even though that generates a result that was used in the previous pass through the loop when it called successor n-1 times). In other words, you've just made an O(n2) operation that looks like an O(n) operation, leaving a performance-cost bomb for whoever else uses your code.
This is the price of a fully Unicode-aware string library.
Anyhow, to answer your actual question — there are two schools of thought for subscripts and domain checking:
Have an optional return type: func subscript(index: Index) -> Element?
This makes sense when there's no sensible way for a client to check whether an index is valid without performing the same work as a lookup — e.g. for a dictionary, finding out if there's a value for a given key is the same as finding out what the value for a key is.
Require that the index be valid, and make a fatal error otherwise.
The usual case for this is situations where a client of your API can and should check for validity before accessing the subscript. This is what Swift arrays do, because arrays know their count and you don't need to look into an array to see if an index is valid.
The canonical test for this is precondition: e.g.
func subscript(index: Index) -> Element {
precondition(isValid(index), "index must be valid")
// ... do lookup ...
}
(Here, isValid is some operation specific to your class for validating an index — e.g. making sure it's > 0 and < count.)
In just about any use case, it's not idiomatic Swift to return a "real" value in the case of a bad index, nor is it appropriate to return a sentinel value — separating in-band values from sentinels is the reason Swift has Optionals.
Which of these is more appropriate for your use case is... well, since your use case is problematic to being with, it's sort of a wash. If you precondition that index < count, you still incur an O(n) cost just to check that (because a String has to examine its contents to figure out which sequences of bytes constitute each character before it knows how many characters it has). If you make your return type optional, and return nil after calling advancedBy or count, you've still incurred that O(n) cost.

Declaring a variable without assigning

Any way to declare a new variable in F# without assigning a value to it?
See Aidan's comment.
If you insist, you can do this:
let mutable x = Unchecked.defaultof<int>
This will assign the absolute zero value (0 for numeric types, null for reference types, struct-zero for value types).
It would be interesting to know why the author needs this in F# (simple example of intended use would suffice).
But I guess one of the common cases when you may use uninitialised variable in C# is when you call a function with out parameter:
TResult Foo<TKey, TResult>(IDictionary<TKey, TResult> dictionary, TKey key)
{
TResult value;
if (dictionary.TryGetValue(key, out value))
{
return value;
}
else
{
throw new ApplicationException("Not found");
}
}
Luckily in F# you can handle this situation using much nicer syntax:
let foo (dict : IDictionary<_,_>) key =
match dict.TryGetValue(key) with
| (true, value) -> value
| (false, _) -> raise <| ApplicationException("Not Found")
You can also use explicit field syntax:
type T =
val mutable x : int
I agree with everyone who has said "don't do it". However, if you are convinced that you are in a case where it really is necessary, you can do this:
let mutable naughty : int option = None
...then later to assign a value.
naughty <- Some(1)
But bear in mind that everyone who has said 'change your approach instead' is probably right. I code in F# full time and I've never had to declare an unassigned 'variable'.
Another point: although you say it wasn't your choice to use F#, I predict you'll soon consider yourself lucky to be using it!
F# variables are by default immutable, so you can't assign a value later. Therefore declaring them without an initial value makes them quite useless, and as such there is no mechanism to do so.
Arguably, a mutable variable declaration could be declared without an initial value and still be useful (it could acquire an initial default like C# variables do), but F#'s syntax does not support this. I would guess this is for consistency and because mutable variable slots are not idiomatic F# so there's little incentive to make special cases to support them.

Resources