Extensions of generic types in Swift 4 - swift

I have two protocols and a generic struct:
public protocol OneDimensionalDataPoint {
/// the y value
var y: Double { get }
}
public protocol TwoDimensionalDataPoint: OneDimensionalDataPoint {
/// the x value
var x: Double { get }
}
public struct DataSet<Element: OneDimensionalDataPoint> {
/// the entries that this dataset represents
private var _values: [Element]
//...implementation
}
extension DataSet: MutableCollection {
public typealias Element = OneDimensionalDataPoint
public typealias Index = Int
public var startIndex: Index {
return _values.startIndex
}
public var endIndex: Index {
return _values.endIndex
}
public func index(after: Index) -> Index {
return _values.index(after: after)
}
public subscript(position: Index) -> Element {
get{ return _values[position] }
set{ self._values[position] = newValue }
}
}
There is a large number of methods that apply to DataSet only when it's Element is a TwoDimensionalDataPoint. So I made an extension like so:
extension DataSet where Element: TwoDimensionalDataPoint {
public mutating func calcMinMaxX(entry e: Element) {
if e.x < _xMin {
_xMin = e.x
}
if e.x > _xMax {
_xMax = e.x
}
}
}
The compiler doesn't like this, and says:
Value of type 'DataSet.Element' (aka
'OneDimensionalDataPoint') has no member 'x'
Shouldn't this be fine since I constrained Element to TwoDimensionalDataPoint in the extension?

After I popped it into Xcode I was able to get a better understanding of what was going on,
Your issue is your type alias is overriding your generic type,
Rename your generic name to T and assign Element to T
public typealias Element = T
or your typealias like:
public typealias DataElement = OneDimensionalDataPoint
or just drop the typealias all together.

Related

When declaring static variable for conformance to AdditiveArithmetic, cannot call instance member from same type

I know this sounds crazy for a 10-year-old, but because S4TF doesn't work for me, I'm building my own neural network library in Swift. (I haven't gotten that far.) I'm creating a structure that conforms to AdditiveArithmetic. It also uses Philip Turner's Differentiable, but that's unimportant.
Anyway, when defining the zero variable, I call another variable dimen, defined in the same structure. This raises an error: instance member 'dimen' cannot be used on type 'Electron<T>'
note: the structure I am creating is going to be used to create a multi-dimensional array for neural networks.
Total code (stripped down to remove unimportant bits):
public struct Electron<T> where T: ExpressibleByFloatLiteral, T: AdditiveArithmetic {
var energy: [[Int]: T] = [:]
var dimen: [Int]
public init(_ dim: [Int], with: ElectronInitializer) {
self.dimen = dim
self.energy = [:]
var curlay = [Int](repeating: 0, count: dimen.count)
curlay[curlay.count-1] = -1
while true {
var max: Int = -1
for x in 0..<curlay.count {
if curlay[curlay.count-1-x] == dimen[curlay.count-1-x]-1 {
max = curlay.count-1-x
}
else {break}
}
if max == 0 {break}
else if max != -1 {
for n in max..<curlay.count {
curlay[n] = -1
}
curlay[max-1] += 1
}
curlay[curlay.count-1] += 1
print(curlay)
energy[curlay] = { () -> T in
switch with {
case ElectronInitializer.repeating(let value):
return value as! T
case ElectronInitializer.random(let minimum, let maximum):
return Double.random(in: minimum..<maximum) as! T
}
}()
}
}
subscript(_ coordinate: Int...) -> T {
var convertList: [Int] = []
for conversion in coordinate {
convertList.append(conversion)
}
return self.energy[convertList]!
}
public mutating func setQuantum(_ replace: T, at: [Int]) {
self.energy[at]! = replace
}
}
extension Electron: AdditiveArithmetic {
public static func - (lhs: Electron<T>, rhs: Electron<T>) -> Electron<T> where T: AdditiveArithmetic, T: ExpressibleByFloatLiteral {
var output: Electron<T> = lhs
for value in lhs.energy {
output.energy[value.key] = output.energy[value.key]!-rhs.energy[value.key]!
}
return output
}
public static var zero: Electron<T> {
return Electron.init(dimen, with: ElectronInitializer.repeating(0.0))
}
static prefix func + (x: Electron) -> Electron {
return x
}
public static func + (lhs: Electron<T>, rhs: Electron<T>) -> Electron<T> where T: AdditiveArithmetic, T: ExpressibleByFloatLiteral {
var output: Electron<T> = lhs
for value in lhs.energy {
output.energy[value.key] = output.energy[value.key]!+rhs.energy[value.key]!
}
return output
}
}
public enum ElectronInitializer {
case random(Double, Double)
case repeating(Double)
}
Error:
NeuralNetwork.xcodeproj:59:30: error: instance member 'dimen' cannot be used on type 'Electron'
return Electron.init(dimen, with: ElectronInitializer.repeating(0.0))
I don't know what's happening, but thanks in advance. I'm new to Stack Overflow, so sorry if I did something wrong.
The root of the problem is that dimen is an instance property, while zero is a static property. In a static context, you don't have an instance from which to access dimen, and so the compiler gives you the error. static properties and methods are a lot like global variables and free-functions with respect to accessing instance properties and methods. You'd have to make an instance available somehow. For a static function, you could pass it in, but for a static computed property, you'd either have to store an instance in a stored static property, which isn't allowed for generics, or you'd have to store it in a global variable, which isn't good either, and would be tricky to make work for all the possible T.
There are ways to do what you need though. They all involve implementing some special behavior for a zero Electron rather than relying on access to an instance property in your static .zero implementation. I made some off-the-cuff suggestions in comments, which would work; however, I think a more elegant solution is to solve the problem by creating a custom type for energy, which would require very few changes to your existing code. Specifically you could make an Energy type nested in your Electron type:
internal struct Energy: Equatable, Sequence {
public typealias Value = T
public typealias Key = [Int]
public typealias Element = (key: Key, value: Value)
public typealias Storage = [Key: Value]
public typealias Iterator = Storage.Iterator
public typealias Keys = Storage.Keys
public typealias Values = Storage.Values
private var storage = Storage()
public var keys: Keys { storage.keys }
public var values: Values { storage.values }
public var count: Int { storage.count }
public init() { }
public subscript (key: Key) -> Value? {
get { storage.isEmpty ? .zero : storage[key] }
set { storage[key] = newValue }
}
public func makeIterator() -> Iterator {
storage.makeIterator()
}
}
The idea here is that when energy.storage is empty, it returns 0 for any key, which allows you to use it as a .zero value. I've made it internal, because energy defaults to internal, and so I've done a minimalist job of wrapping a Dictionary, mainly providing subscript operator, and making it conform to Sequence, which is all that is needed by code you provided.
The only changes needed in the rest of your code are to change the definition of energy
var energy: Energy
Then to set it in your initializer, by-passing the bulk of your init when dim is empty.
public init(_ dim: [Int], with: ElectronInitializer) {
self.dimen = dim
self.energy = Energy() // <- Initialize `energy`
// Empty dim indicates a zero electron which doesn't need the
// rest of the initialization
guard dim.count > 0 else { return }
var curlay = [Int](repeating: 0, count: dimen.count)
curlay[curlay.count-1] = -1
while true {
var max: Int = -1
for x in 0..<curlay.count {
if curlay[curlay.count-1-x] == dimen[curlay.count-1-x]-1 {
max = curlay.count-1-x
}
else {break}
}
if max == 0 {break}
else if max != -1 {
for n in max..<curlay.count {
curlay[n] = -1
}
curlay[max-1] += 1
}
curlay[curlay.count-1] += 1
print(curlay)
energy[curlay] = { () -> T in
switch with {
case ElectronInitializer.repeating(let value):
return value as! T
case ElectronInitializer.random(let minimum, let maximum):
return Double.random(in: minimum..<maximum) as! T
}
}()
}
}
And then of course, to change how you create it in your zero property
public static var zero: Electron<T> {
return Electron.init([], with: ElectronInitializer.repeating(0.0))
}
ElectronInitializer isn't actually used in this case. It's just a required parameter of your existing init. This suggests an opportunity to refactor initialization, so you could have an init() that creates a zero Electron in addition to your existing init(dim:with:)

calling functions on subscript returnvalue

Im experimenting with subscripts and generics, and what I am trying to do is this:
heap[0]!.hasLeftChild
Where my heap class looks something like this:
public class Heap<T> where T:HeapSubscriptable {
private var size = Int()
private var valueList = [T]()
public var capacity = 3
// subscript setter
subscript(i: Int) -> T? {
if i < self.size {
return valueList[i]
} else {
return nil
}
}
...
}
To allow this i made a protocol extension:
public protocol HeapSubscriptable {
var hasLeftChild: Bool{ get }
}
extension HeapSubscriptable {
public var hasLeftChild: Bool {
// return (self.size > 1+i*2 ) // <-- I want to get a hold of this i
}
}
extension Int : HeapSubscriptable{}
But to calculate this I need access to the subscript parameter i, so that i can use its index in my array and do magic on it and see if it actually has a left child. Is there away to access it?

Conforming a new protocol to Sequence with a default makeIterator() implementation

I made a (very basic) BinaryTree protocol:
public enum BinaryTreeChildSide {
case left, right
}
public protocol BinaryTree {
associatedtype Element
associatedtype Index
func child(of index: Index, side: BinaryTreeChildSide) -> Index?
var rootIndex: Index? { get }
subscript(position: Index) -> Element { get }
}
For a basic iterative in-order traversal, I made a BinaryTreeIterator (note that I don't implement Sequence just yet):
public extension BinaryTree {
func makeIterator() -> BinaryTreeIterator<Self> {
return BinaryTreeIterator(self)
}
}
public struct BinaryTreeIterator<Tree: BinaryTree>: IteratorProtocol {
private let tree: Tree
private var stack: [Tree.Index]
private var index: Tree.Index?
private init(_ tree: Tree) {
self.tree = tree
stack = []
index = tree.rootIndex
}
public mutating func next() -> Tree.Element? {
while let theIndex = index {
stack.append(theIndex)
index = tree.child(of: theIndex, side: .left)
}
guard let currentIndex = stack.popLast() else { return nil }
defer { index = tree.child(of: currentIndex, side: .right) }
return tree[currentIndex]
}
}
Implementing a binary heap to this protocol is also pretty straight-forward:
public struct BinaryHeap<Element> {
private var elements: [Element]
public init(_ elements: [Element]) {
self.elements = elements
}
}
extension BinaryHeap: BinaryTree {
private func safeIndexOrNil(_ index: Int) -> Int? {
return elements.indices.contains(index) ? index : nil
}
public func child(of index: Int, side: BinaryTreeChildSide) -> Int? {
switch side {
case .left: return safeIndexOrNil(index * 2 + 1)
case .right: return safeIndexOrNil(index * 2 + 2)
}
}
public var rootIndex: Int? { return safeIndexOrNil(0) }
public subscript(position: Int) -> Element {
return elements[position]
}
}
So far, so good. I can now make a simple heap and iterate through its elements:
let heap = BinaryHeap([4, 2, 6, 1, 3, 5, 7])
var iterator = heap.makeIterator()
while let next = iterator.next() {
print(next, terminator: " ")
}
// 1 2 3 4 5 6 7
This works, but of course the goal of implementing makeIterator() is to conform to Sequence. however, if I replace
public protocol BinaryTree {
with
public protocol BinaryTree: Sequence {
then the compiler complains that BinaryHeap doesn't implement Sequence because the associated type Iterator couldn't be inferred. If I manually specify the Iterator type with
extension BinaryHeap: BinaryTree {
typealias Iterator = BinaryTreeIterator<BinaryHeap>
...
}
then the compiler shows an error that Iterator circularly references itself. So that might be why the Iterator type couldn't be inferred.
Interestingly, it works if I wrap my custom BinaryTreeIterator in an AnyIterator instance:
public extension BinaryTree {
func makeIterator() -> AnyIterator<Element> {
return AnyIterator(BinaryTreeIterator(self))
}
}
let heap = BinaryHeap([4, 2, 6, 1, 3, 5, 7])
for number in heap {
print(number, terminator: " ")
}
// 1 2 3 4 5 6 7
Apple's own IndexingIterator seems to work in a similar fashion to my BinaryTreeIterator:
public struct IndexingIterator<
Elements : IndexableBase
// FIXME(compiler limitation):
// Elements : Collection
> : IteratorProtocol, Sequence {
...
}
From the source code. Maybe the problem I'm facing might also be because of the compiler limitation mentioned there, but I don't know for sure.
Is there a way to conform BinaryTree to Sequence without using AnyIterator?
This is the farthest I could take it. Now the compiler will still complain about the heap not containing any makeIterator member
(which I thought was included by default once someone conforms to sequence—wrong turns out one must conform to Sequence ​and​ IteratorProtocol for the default implementation) and having a next—but once you add those methods its smooth sailing.
So makeIterator + next method to make Mr/Mrs/Preferred Gender Pronoun compiler happy.
public enum BinaryTreeChildSide {
case left, right
}
public struct BinaryTreeIterator<Tree: BinaryTree>: Sequence, IteratorProtocol {
private let tree: Tree
private var stack: [Tree.Index]
private var index: Tree.Index?
private init(_ tree: Tree) {
self.tree = tree
stack = []
index = tree.rootIndex
}
public mutating func next() -> Tree.Element? {
while let theIndex = index {
stack.append(theIndex)
index = tree.child(of: theIndex, side: .left)
}
guard let currentIndex = stack.popLast() else { return nil }
defer { index = tree.child(of: currentIndex, side: .right) }
return tree[currentIndex]
}
}
public protocol BinaryTree: Sequence {
associatedtype Element
associatedtype Index
func child(of index: Index, side: BinaryTreeChildSide) -> Index?
var rootIndex: Index? { get }
subscript(position: Index) -> Element { get }
}
extension BinaryTree {
func makeIterator() -> BinaryTreeIterator<Self> {
return BinaryTreeIterator(self)
}
}
extension BinaryHeap {
private func safeIndexOrNil(_ index: Int) -> Int? {
return elements.indices.contains(index) ? index : nil
}
public func child(of index: Int, side: BinaryTreeChildSide) -> Int? {
switch side {
case .left: return safeIndexOrNil(index * 2 + 1)
case .right: return safeIndexOrNil(index * 2 + 2)
}
}
public var rootIndex: Int? { return safeIndexOrNil(0) }
public subscript(position: Int) -> Element {
return elements[position]
}
}
public struct BinaryHeap<Element> {
private var elements: [Element]
public init(_ elements: [Element]) {
self.elements = elements
}
}
let heap = BinaryHeap([4, 2, 6, 1, 3, 5, 7])
var iterator = heap.makeIterator()
while let next = iterator.next() {
print(next, terminator: " ")
}
Apparently it was a Swift bug: my code compiles fine using Swift 3.1.

Add sort to array wrapping class

The following code is from this answer: https://stackoverflow.com/a/28191539/4096655
public class SynchronizedArray<T> {
private var array: [T] = []
private let accessQueue = dispatch_queue_create("SynchronizedArrayAccess", DISPATCH_QUEUE_SERIAL)
public func append(newElement: T) {
dispatch_async(self.accessQueue) {
self.array.append(newElement)
}
}
public subscript(index: Int) -> T {
set {
dispatch_async(self.accessQueue) {
self.array[index] = newValue
}
}
get {
var element: T!
dispatch_sync(self.accessQueue) {
element = self.array[index]
}
return element
}
}
}
var a = SynchronizedArray<Int>()
a.append(1)
a.append(2)
a.append(3)
// can be empty as this is non-thread safe access
println(a.array)
// thread-safe synchonized access
println(a[0])
println(a[1])
println(a[2])
I am doing something very much like but am having trouble setting up a sort to pass to the array of generics. Ideally I'd like a sortInPlace but am not sure how to do it.
If you want to sort the wrapped array, then one way is to constrain T to a type conforming to Comparable. If you add this restriction, then a sorting function is easy to implement, simply ask the array to sort itself:
public class SynchronizedArray<T: Comparable> {
...
public func sortInPlace() {
array.sortInPlace(<)
}
For custom classes, you need to add an extension conforming to Comparable, and overload the == and < operators (reference here)
extension MyClass: Comparable {
}
func ==(lhs: MyClass, rhs: MyClass) -> Bool {
}
func <(lhs: MyClass, rhs: MyClass) -> Bool {
}
var a = SynchronizedArray<MyClass>()

Swift subscript with different signature for the getter and setter

Is it possible to have a subscript in Swift that has different signatures for the getter and setter?
For example, I want the getter to return a Set<Int> and the setter to take an Int (not a Set<Int>).
This code won't compile but it gives you an idea of what I'm trying to do:
struct Foo{
subscript(index: Int)->String{
get{
return "bar" // returns a String
}
set(newValue: String?){ // takes a String? instead of a String
print(newValue)
}
}
}
How can I do this?
This is very ugly, and I strongly discourage you from doing so, but technically this is possible:
struct Foo {
subscript(concreteValueFor index: Int) -> String {
return "Get concrete \(index)"
}
subscript(optionalValueFor index: Int) -> String? {
get { return nil }
set { print("Set optional \(index)") }
}
}
var foo = Foo()
foo[concreteValueFor: 1] // Returns "Get concrete 1"
foo[optionalValueFor: 2] = "" // Prints "Set optional 2"
For a multimap some time ago I made something like this:
public struct Multimap<Key: Hashable, Value: Hashable>: CollectionType {
public typealias _Element = Set<Value>
public typealias Element = (Key, _Element)
public typealias Index = DictionaryIndex<Key, _Element>
public typealias Generator = DictionaryGenerator<Key, _Element>
private typealias Storage = [Key: _Element]
private var storage = Storage()
public var startIndex: Index { return storage.startIndex }
public var endIndex: Index { return storage.endIndex }
public subscript(position: Index) -> _Element { return storage[position].1 }
public subscript(position: Index) -> Element { return storage[position] }
subscript(key: Key) -> Set<Value> {
get { return storage[key] ?? Set<Value>() }
set { storage[key] = newValue.isEmpty ? nil : newValue }
}
public func generate() -> Generator { return storage.generate() }
}
Usage:
var foo = Multimap<Int, String>()
foo[0] // Returns an emtpy Set<String>
foo[0].insert("Ook") // Inserts a value at index 0
foo[0].insert("Eek")
foo[0] // Now this returns a set { "Ook", "Eek" }
foo[1].insert("Banana")
foo[1].insert("Book")
foo[0].unionInPlace(foo[1])
foo[0] // Returns a set { "Banana", "Ook", "Eek", "Book" }