Why does adding mutable produce different hash values? - hash

I have a simple struct like this with no custom == or hash() methods:
struct IntroductionMessage
message::String
end
When I call hash() both return the same value:
say_hello_introduction = IntroductionMessage("Hello World")
say_hello_introduction_alternate = IntroductionMessage("Hello World")
hash(say_hello_introduction))
hash(say_hello_introduction_alternate))
# Output:
3650104434
3650104434
When I add the mutable keyword, so it's now mutable struct IntroductionMessage, the hash() values are different:
2957940122
238434212
The string itself never changed, so why does adding mutable produce a different result?

By default immutable structs are hashed by value while mutable structs are hashed by reference. This matches the default equality operations.

Related

What does Hash Values for Set Types in swift?

when i read swift documentation i can not understand what that mean?.
A type must be hashable in order to be stored in a set—that is, the type must provide a way to compute a hash value for itself. A hash value is an Int value that is the same for all objects that compare equally, such that if a == b, it follows that a.hashValue == b.hashValue.
Sets are designed for performance. The contains(_:) method on Set is O(1) complexity meaning it takes a constant amount of time to perform no matter the size of the set. contains(_:) on an Array is O(n) meaning the time to determine if the array contains an element increases as the size of the array increases.
How does a Set do that? It uses a hashValue for the items of the Set and contains an internal dictionary like structure that maps the hashValue to the list of items with that hashValue. This makes testing equality of complex structures (like String) very quick because Set first tests if two values have the same hashValue. If the hashValues are different, it doesn't need to check the contents of the structs themselves.
To test if the Set contains a value, it is necessary to only look up the hashValue in the dictionary and then compare the item to the values that match.
So, for items to be contained in a Set, it is important to provide a hashing function that:
Is the same if two structs/objects are equal. (absolute requirement)
Computes a wide range of hashValues so that the items are widely distributed and don't require falling back to the slower check for equality. (for good performance)
Here is an example of a Hashable struct that is appropriate for storage in a Set:
struct Option: Hashable, CustomStringConvertible {
var title: String
var key: String
var value: Int
var description: String { return "{title: \"\(title)\", key: \"\(key)\", value: \(value)}" }
func hash(into hasher: inout Hasher) {
hasher.combine(title)
hasher.combine(key)
}
static func ==(lhs: Option, rhs: Option) -> Bool {
return lhs.title == rhs.title && lhs.key == rhs.key
}
}
Note: In this example, only the title and key properties are considered for equality. Two structs can be equal even if they have different value properties. The hash(into:) function likewise only considers the title and key properties.

How to initialize an array inside a dictionary?

I have a dictionary declared like this:
var myDict = [Int : [Int]]()
The array in it is not initialized, so every time I have to check it first:
if (myDict[idx] == nil) {
myDict[idx] = []
}
How to initialize it as an empty array in MyDict declaration?
I think you could be misunderstanding something pretty key - let's make sure:
The way the dictionary works, is not to have one array, but an array for each key.
Each value of 'idx' you request the array for returns a different array.
You can't expect it to return an empty array - a dictionary is meant to return a nil value for a key that hasn't been set. To do what you're trying, the following would probably do the trick:
myDict[idx] = myDict[idx] ?? []
That's what dictionary do if you try to retrieve a key for which no value exists.
You can subclass Dictionary and override the subscript func to get what you want like this. Or simply write an extension, or write a operator defination to use a different symbol.
“You can also use subscript syntax to retrieve a value from the dictionary for a particular key. Because it is possible to request a key for which no value exists, a dictionary’s subscript returns an optional value of the dictionary’s value type. ”
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2.1).” iBooks. https://itunes.apple.com/cn/book/swift-programming-language/id881256329?l=en&mt=11
You can initialize it this way
myDict.forEach {
(var dictElement) -> () in
dictElement.1 = [Int]()
}

Why does not Dictionary adopt MutableCollectionType protocol?

While implementing a custom collection type (and therefore making it to adhere to CollectionType protocol) I came to wonder why MutableCollectionType is not adopted by Dictionary type?
From the documentation for MutableCollectionType:
A collection that supports subscript assignment.
For any instance a of a type conforming to MutableCollectionType, :
a[i] = x
let y = a[i]
is equivalent to:
a[i] = x
let y = x
Therefore, it would seem "logical" that Dictionary also adopts this protocol. However, after checking out header files as well as docs, it seems that only Array and related types do that.
What's so special about MutableCollectionType, or about Dictionary, or both for that matter? Should my dictionary-like custom collection type also avoid adopting MutableCollectionType for some reason?
A glance through the protocol reference describes it as having methods like sort and partition. It also has an internal type call SubSequence. These are meaningless with dictionaries. There are no order within a dictionary.
From the headers:
Whereas an arbitrary sequence may be consumed as it is traversed, a collection is multi-pass: any element may be revisited merely by saving its index.
That makes no sense for a dictionary, as a dictionary is unordered. Just because the entry keyed by "howdy" is at index 2 right now does not mean it will be at index 2 one minute from now. In particular, it makes no sense to say "insert this key at index 2" - it is the keys and the internal hashing that provide the order. The indexes have no persistent life of their own. Thus, it is a collection (it has indexes), but not a mutable collection (you can't write into it by index).
To understand the declaration of MutableCollectionType protocol, you first need to know a concept called subscript.
When you write “let y = dic[key]”, Swift is calling a method called subscript getter:
subscript (key: Key) -> Value? { get }
And when you write “dic[key] = x”, Swift is calling a method called subscript setter:
subscript (key: Key) -> Value? { set }
Now let's look at the MutableCollectionType protocol. Dictionary does not conform to MutableCollectionType. because the required methods of this protocol is not implemented in Dictionary.
One of the required method is
public subscript (position: Self.Index) -> Self.Generator.Element { get set }
This subscript method is not the same as the above two we use every day. The type of position is Self.Index, which is DictionaryIndex<Key, Value> for Dictionary type. And the return type Self.Generator.Element is (Key, Value). I think This index type DictionaryIndex is something related to the hash table implementation, which can be used to directly refer to an hash table element. When you use the setter of the subscript you will write something like
dic[index] = (key, value)
It certainly makes no sense to replace a hash map element with another key value pair. This subscript setter is never implemented by Dictionary, so it does not conform to MutableCollectionType protocol.

Swift wrapper class

I was watching a talk on swift optimization earlier and they were using an example of a struct with 5 variables 3 strings an array and a dictionary. They said to lower your reference count you could use a wrapper class. Can someone just make a dummy one to I might be able to understand it better.
A wrapper class would be used if you have performance issues with a struct which has many properties which are reference types.
A generic wrapper class:
class Wrapper<T> {
var value: T // or "let" instead of "var"
init(_ value: T) { self.value = value }
}
This is because if you assign it to another variable all pointers of the properties get copied and therefore all reference counts (see ARC) get incremented (and decremented at the end).
This problem mainly occurs when you are looping over large arrays of such structs where at each iteration a new variable gets created.
With a wrapper class only its reference count gets incremented and decremented once.
Example:
struct Big {
// "n" properties which have reference semantics
...
...
}
// "m" count
let hugeArray = [Big(), Big(), Big(), ...]
// m * n reference count operations (+1, -1)
for element in hugeArray {
// do something
}
// if huge array is of type [Wrapper<Big>]
// m * 1 reference count operations (+1, -1)
for element in hugeArray {
// do something
}
Side note: Such a class could improve performance. Use it with care if you write to it, assign it or pass it as parameter since it "changes" the semantics of your wrapped type and is no value type.

Implementing a multimap in Swift with Arrays and Dictionaries

I'm trying to implement a basic multimap in Swift. Here's a relevant (non-functioning) snippet:
class Multimap<K: Hashable, V> {
var _dict = Dictionary<K, V[]>()
func put(key: K, value: V) {
if let existingValues = self._dict[key] {
existingValues += value
} else {
self._dict[key] = [value]
}
}
}
However, I'm getting an error on the existingValues += value line:
Could not find an overload for '+=' that accepts the supplied arguments
This seems to imply that the value type T[] is defined as an immutable array, but I can't find any way to explicitly declare it as mutable. Is this possible in Swift?
The problem is that you are defining existingValues as a constant with let. However, I would suggest changing the method to be:
func put(key: K, value: V) {
var values = [value]
if let existingValues = self._dict[key] {
values.extend(existingValues)
}
self._dict[key] = values
}
}
I feel that the intent of this is clearer as it doesn't require modifying the local array and reassigning later.
if var existingValues = self._dict[key] { //var, not let
existingValues += value;
// should set again.
self._dict[key] = existingValues
} else {
self._dict[key] = [value]
}
Assignment and Copy Behavior for Arrays
The assignment and copy behavior for Swift’s Array type is more complex than for its Dictionary type. Array provides C-like performance when you work with an array’s contents and copies an array’s contents only when copying is necessary.
If you assign an Array instance to a constant or variable, or pass an Array instance as an argument to a function or method call, the contents of the array are not copied at the point that the assignment or call takes place. Instead, both arrays share the same sequence of element values. When you modify an element value through one array, the result is observable through the other.
For arrays, copying only takes place when you perform an action that has the potential to modify the length of the array. This includes appending, inserting, or removing items, or using a ranged subscript to replace a range of items in the array. If and when array copying does take place, the copy behavior for an array’s contents is the same as for a dictionary’s keys and values, as described in Assignment and Copy Behavior for Dictionaries.
See: https://itunes.apple.com/us/book/the-swift-programming-language/id881256329?mt=11
Buckets is a data structures library for swift. It provides a multimap and allows subscript notation.
One easy way to implement a multi-map is to use a list of pairs (key, value) sorted by key, using binary search to find ranges of entries. This works best when you need to get a bunch of data, all at once. It doesn't work so well when you are constantly deleting and inserting elements.
See std::lower_bound from C++ for a binary search implementation which can be easily written in swift.