Consider a Generically constructed Node for a DoublyLinkedList:
public class Node<T> {
var value: T
var next: Node<T>?
weak var previous: Node<T>?
init(value: T) {
self.value = value
}
}
public class DoublyLinkedList<T> {
var head: Node<T>?
private var tail: Node<T>?
public func append(value: T) {
let newNode = Node(value: value)
if let tailNode = tail {
newNode.previous = tailNode
tailNode.next = newNode
} else {
head = newNode
}
tail = newNode
}
....
How do I make the DoublyLinkedList even more Generic?
(i.e. I subclassed Node so that I could implement some specific behaviors via inheritance). I can't seem to synthesize a DoublyLinkedList of my subclass because it is looking for the "Concrete"? type of Node
class TransactionFilterNode: Node<Search> {
let seedTransactions: [Transaction]
init(search: Search, allTransactions: [Transaction]){
self.seedTransactions = allTransactions
super.init(value: search)
}
I can't seem to get this to be inserted or appended to DoublyLinkedList because DoublyLinkedList is looking for a Node, not a subclass of Node.
Edit: Solved
The solution was to pull the call for Node into the function call parameter so that I could pass a subclassed version. See below.
So your append method expects a type T (which in your case is Search), while you are directly subclassing a Node.
So you can
Option 1: create append that accepts the Node, e.g.:
func append(value: T) {
let newNode = Node(value: value)
append(newNode: newNode)
}
func append(newNode: Node<T>) {
if let tailNode = tail {
newNode.previous = tailNode
tailNode.next = newNode
} else {
head = newNode
}
tail = newNode
}
So now you can
let x = DoublyLinkedList<Search>()
let y = TransactionFilterNode(...)
x.append(newNode: y) // No problem
Option 2: subclass Search instead of subclassing Node
I.e. maybe instead of class TransactionFilterNode: Node<Search> you meant to say class TransactionFilter: Search?
My doubly linked list is generic over everything because I conceal Node from the user by embedding it.
He simply asks for a BiLinkedList or a BiLinkedList or whatever he wants to list. Only access via subscripts requires his objects to be Equatable. Note that all references to Node are private.
Here are my headers:
public struct BiLinkedList<Element> {
var head: Node<Element>?
var tail: Node<Element>?
public init(_ array: [Element] = []) {}
private mutating func copyNodes() {}
public var peekFirst: Element? { get }
public var peekLast: Element? { get }
public mutating func push(_ element: Element)
public mutating func append(_ element: Element)
public mutating func pop() -> Element?
public mutating func removeLast() -> Element?
}
extension BiLinkedList {
class Node<Element> {
var element: Element
weak var previous: Node?
var next: Node?
init(_ element: Element, previous: Node? = nil, next: Node? = nil)
}
}
extension BiLinkedList where Element: Equatable {
private func firstNode(containing value: Element) -> Node<Element>?
private func lastNode(containing value: Element) -> Node<Element>?
public mutating func insert(_ element: Element, beside value: Element, before: Bool) -> Bool
}
extension BiLinkedList {
public mutating func removeFirst(_ value: Element) -> Bool
public mutating func removeLast(_ value: Element) -> Bool
public mutating func removeAll(_ value: Element)
public mutating func replaceFirst(_ element: Element, with value: Element) -> Bool
public mutating func replaceLast(_ element: Element, with value: Element) -> Bool
}
extension BiLinkedList: Collection {
public struct Index: Comparable {
var node: Node<Element>?
public static func == (lhs: Index, rhs: Index) -> Bool {}
static public func <(lhs: Index, rhs: Index) -> Bool {}
}
public var startIndex: Index
public var endIndex: Index
public func index(after i: Index) -> Index {}
public subscript(position: Index) -> Element {}
public subscript(position: Int) -> Element? {}
}
extension BiLinkedList: Sequence {
public func makeIterator() -> LinkedListIterator {}
public struct LinkedListIterator: IteratorProtocol {
private var currentNode: Node<Element>?
fileprivate init(node: Node<Element>?) {}
public func next() -> Element? {}
}
}
Related
Topic: Generic Where Clauses
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
struct Stack<Element>: Container {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
mutating func append(_ item: Element) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Element {
return items[i]
}
}
func allItemsMatch<C1: Container, C2: Container>
(_ someContainer: C1, _ anotherContainer: C2) -> Bool
where C1.Item == C2.Item, C1.Item: Equatable {
if someContainer.count != anotherContainer.count {
return false
}
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
return true
}
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
var arrayOfStrings = ["uno", "dos", "tres"]
Error comes here in if-else control flow
if allItemsMatch(stackOfStrings, arrayOfStrings) {
print("All items match.")
} else {
print("Not all items match.")
}
Error says that "arrayOfStrings" doesn't conform to the Container Protocol.
Tried many times but not able to figure out
Error exactly says - " Global function 'allItemsMatch' requires that '[String]' conform to 'Container' "
As already mentioned in comments you forgot to declare that Array conforms to the Container protocol.
extension Array: Container { }
Not related to your question but you should also make your Stack structure conform to Sequence as well. It will allow you to use Sequence method elementsEqual
func elementsEqual<OtherSequence>(_ other: OtherSequence) -> Bool where OtherSequence : Sequence, Self.Element == OtherSequence.Element
So just add an index property to your Stack type and implement Sequence next property as follow:
struct Stack<Element>: Container {
typealias Item = Element
var items = [Item]()
mutating func push(_ item: Item) { items.append(item) }
mutating func pop() -> Item { items.removeLast() }
mutating func append(_ item: Item) { push(item) }
var count: Int { items.count }
subscript(i: Int) -> Item { items[i] }
var index: Int = 0
}
extension Stack: Sequence, IteratorProtocol {
mutating func next() -> Item? {
guard index < items.endIndex else { return nil }
defer { index += 1}
return items[index]
}
}
Playground testing:
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
var arrayOfStrings = ["uno", "dos", "tres"]
stackOfStrings.elementsEqual(arrayOfStrings) // true
The swift language guide gives this protocol:
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
with this conforming struct:
struct IntStack: Container {
// original IntStack implementation
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
// conformance to the Container protocol
typealias Item = Int
mutating func append(_ item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
Why is typealias Item = Int needed? It seems that "Item" can be inferred already.
You are actually right. The Item type can be inferred, and typealias Item = Int is not needed.
You can remove that line and see, that the code compiles.
I don't know why swift.org use associatedtype like that but generally swift.org define associatedtype as following:
An associated type gives a placeholder name to a type that is used as
part of the protocol
and here is the right sample
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
struct IntStack: Container {
// original IntStack implementation
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
// conformance to the Container protocol
typealias Item = Int
mutating func append(_ item: Item) {
self.push(item)
}
var count: Item {
return items.count
}
subscript(i: Item) -> Item {
return items[i]
}
}
I guess it's a mistake of swift.org's content maker
I agree with Evgeniy that the typealias here isn't needed, but there are cases where it is, specifically if the typealias is not part of any signature. For example, the following is a legal protocol:
protocol Container {
associatedtype Item
}
The only way to conform to that would be with a typealias. In this form it doesn't seem too useful, but consider types with static properties:
protocol ConfigurationType {
static var values: [String: String] {get}
}
protocol Configurable {
associatedtype Configuartion: ConfigurationType
}
I'm not suggesting this particular example is a good use of protocols, but it is legal.
I agree that the documentation here is a bit confusing, but I also wouldn't necessarily use type-inference here. I'd generally suggest using the typealias, but also using it in the methods:
// conformance to the Container protocol
typealias Item = Int
mutating func append(_ item: Item) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Item {
return items[i]
}
But this is a debatable point.
I'm trying to implement a storing weak references solutions from objc talks (https://www.objc.io/blog/2017/12/28/weak-arrays/) but I'm not able to get it working.
The exact error message tells:
'WeakBox' requires that 'WeakArray<Element>.Element' (aka 'Optional<Element>') be a class type
With this code:
final class WeakBox<A: AnyObject> {
weak var unbox: A?
init(_ value: A) {
unbox = value
}
}
struct WeakArray<Element: AnyObject> {
private var items: [WeakBox<Element>] = []
init(_ elements: [Element]) {
items = elements.map { WeakBox($0) }
}
init() {}
}
extension WeakArray: Collection {
var startIndex: Int { return items.startIndex }
var endIndex: Int { return items.endIndex }
subscript(_ index: Int) -> Element? {
return items[index].unbox
}
func index(after idx: Int) -> Int {
return items.index(after: idx)
}
mutating func append(_ element: Element) {
items.append(WeakBox(element))
}
mutating func removeAll() {
items.removeAll()
}
}
**
Update:
**
After some time I realized that error message is completely misleading. The real problem is in calling methods of a Sequence protocol. For example, adding something like this below produces an error message from the above screenshot. But I haven't found a solution yet.
class De {
let de = "de"
}
let de = De()
var ar = WeakArray<De>([])
ar.append(de)
ar.append(de)
ar.forEach({ $0 })
I believe 'Element' is being redefined by the SDK somewhere. Renaming Element to T should fix the issue.
import Foundation
final class WeakBox<T:AnyObject> {
weak var unbox: T?
init(_ value: T?) {
unbox = value
}
}
struct WeakArray<T: AnyObject> {
private var items: [WeakBox<T>] = []
init(_ elements: [T]) {
items = elements.map { WeakBox($0) }
}
init(_ elements: [T?]) {
items = elements.map { WeakBox($0) }
}
mutating func append(_ obj:T?) {
items.append(WeakBox(obj))
}
mutating func remove(at:Int) {
items.remove(at: at)
}
}
extension WeakArray: Collection {
var startIndex: Int { return items.startIndex }
var endIndex: Int { return items.endIndex }
subscript(_ index: Int) -> T? {
return items[index].unbox
}
func index(after idx: Int) -> Int {
return items.index(after: idx)
}
}
If found this stack data structure at Ray Wenderlich and it works well:
public struct Stack<T> {
fileprivate var array = [T]()
public var isEmpty: Bool {
return array.isEmpty
}
public var count: Int {
return array.count
}
public mutating func push(_ element: T) {
array.append(element)
}
public mutating func pop() -> T? {
return array.popLast()
}
public var top: T? {
return array.last
}
}
I'd like to add another method for finding an element within the stack so that I don't try to add an element more than once. For example, I'm keeping a stack of ViewControllers.
var vcStack = Stack<UIViewController>()
vcStack.push(VC1)
vcStack.push(VC2)
I'd like to be able to query the Stack and get back a boolean if the input VC exists (or not), like this:
if vcStack.hasElement(VC1) {
//do something
}
This is pseudo-code - what would the Swift 4 code be?
public var hasElement(_ element: T): -> Bool {
if array.contains(element){
return true
}else{
return false
}
}
If you define your Stack class to require that its elements conform to Equatable:
public struct Stack<T> where T: Equatable {
then your hasElement would be:
public func hasElement(_ element: T) -> Bool {
return array.contains(element)
}
Or you can leave Stack declared as you have it, and add hasElement to an extension:
public extension Stack where T: Equatable {
public func hasElement(_ element: T) -> Bool {
return array.contains(element)
}
}
This allows you have to have a Stack of anything but the hasElement function will only be available if it's a Stack of Equatable values.
struct MenuData {
let title : String!
let imageName : String!
}
class MoreTV: UITableView {
var aryMenu : [MenuData] = [MenuData(title: "My Profile".localized, imageName: "ic-user"),]
}
I have checked all answers about this problem on stackoverflow, but still can not figure out how to fix this.
My model looks like this
protocol Commandable: Equatable {
var condition: Condition? {get set}
func execute() -> SKAction
}
And 3 structs which implement this protocol
struct MoveCommand: Commandable {
var movingVector: CGVector!
//MARK: - Commandable
var condition: Condition?
func execute() -> SKAction {
...
}
}
extension MoveCommand {
// MARK:- Equatable
static func ==(lhs: MoveCommand, rhs: MoveCommand) -> Bool {
return lhs.movingVector == rhs.movingVector && lhs.condition == rhs.condition
}
}
struct RotateCommand: Commandable {
var side: RotationSide!
// MARK: - Commandable
var condition: Condition?
func execute() -> SKAction {
...
}
}
extension RotateCommand {
// MARK: - Equatable
static func ==(lhs: RotateCommand, rhs: RotateCommand) -> Bool {
return lhs.side == rhs.side && lhs.condition == rhs.condition
}
}
The problems start when I am trying to create third structure which has array of [Commandable]:
struct FunctionCommand: Commandable {
var commands = [Commandable]()
The compiler output: Protocol 'Commandable' can only be used as a generic constraint because it has Self or associated type requirements. Then i rewrote my struct in this way:
struct FunctionCommand<T : Equatable>: Commandable {
var commands = [T]()
I resolve this problem but new problem has appeared. Now i can't create FunctionCommand with instances of Rotate and Move command, only with instances of one of them :( :
let f = FunctionCommand(commands: [MoveCommand(movingVector: .zero, condition: nil),
RotateCommand(side: .left, condition: nil)], condition: nil)
Any Help would be appreciated.
Update: That article helped me to figure out - https://krakendev.io/blog/generic-protocols-and-their-shortcomings
What you need to do is to use type erasure, much like AnyHashable does in the Swift Standard Library.
You can't do:
var a: [Hashable] = [5, "Yo"]
// error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements
What you have to do is to use the type-erased type AnyHashable:
var a: [AnyHashable] = [AnyHashable(5), AnyHashable("Yo")]
a[0].hashValue // => shows 5 in a playground
So your solution would be to first split the protocol in smaller parts and promote Equatable to Hashable (to reuse AnyHashable)
protocol Conditionable {
var condition: Condition? { get set }
}
protocol Executable {
func execute() -> SKAction
}
protocol Commandable: Hashable, Executable, Conditionable {}
Then create an AnyCommandable struct, like this:
struct AnyCommandable: Commandable, Equatable {
var exeBase: Executable
var condBase: Conditionable
var eqBase: AnyHashable
init<T: Commandable>(_ commandable: T) where T : Equatable {
self.condBase = commandable
self.exeBase = commandable
self.eqBase = AnyHashable(commandable)
}
var condition: Condition? {
get {
return condBase.condition
}
set {
condBase.condition = condition
}
}
var hashValue: Int {
return eqBase.hashValue
}
func execute() -> SKAction {
return exeBase.execute()
}
public static func ==(lhs: AnyCommandable, rhs: AnyCommandable) -> Bool {
return lhs.eqBase == rhs.eqBase
}
}
And then you can use it like this:
var a = FunctionCommand()
a.commands = [AnyCommandable(MoveCommand()), AnyCommandable(FunctionCommand())]
And you can easily access properties of commands, because AnyCommandable implements Commandable
a.commands[0].condition
You need to remember to now add Hashable and Equatable to all your commands.
I used those implementations for testing:
struct MoveCommand: Commandable {
var movingVector: CGVector!
var condition: Condition?
func execute() -> SKAction {
return SKAction()
}
var hashValue: Int {
return Int(movingVector.dx) * Int(movingVector.dy)
}
public static func ==(lhs: MoveCommand, rhs: MoveCommand) -> Bool {
return lhs.movingVector == rhs.movingVector
}
}
struct FunctionCommand: Commandable {
var commands = [AnyCommandable]()
var condition: Condition?
func execute() -> SKAction {
return SKAction.group(commands.map { $0.execute() })
}
var hashValue: Int {
return commands.count
}
public static func ==(lhs: FunctionCommand, rhs: FunctionCommand) -> Bool {
return lhs.commands == rhs.commands
}
}
I think it can be easily done by introduction of your own CustomEquatable protocol.
protocol Commandable: CustomEquatable {
var condition: String {get}
}
protocol CustomEquatable {
func isEqual(to: CustomEquatable) -> Bool
}
Then, you objects have to conform to this protocol and additionally it should conform Equitable as well.
struct MoveCommand: Commandable, Equatable {
let movingVector: CGRect
let condition: String
func isEqual(to: CustomEquatable) -> Bool {
guard let rhs = to as? MoveCommand else { return false }
return movingVector == rhs.movingVector && condition == rhs.condition
}
}
struct RotateCommand: Commandable, Equatable {
let side: CGFloat
let condition: String
func isEqual(to: CustomEquatable) -> Bool {
guard let rhs = to as? RotateCommand else { return false }
return side == rhs.side && condition == rhs.condition
}
}
All you need to do now is connect your CustomEquatable protocol to Swift Equatable through generic extension:
extension Equatable where Self: CustomEquatable {
static func ==(lhs: Self, rhs: Self) -> Bool {
return lhs.isEqual(to: rhs)
}
}
It's not a perfect solution, but now, you can store your objects in a array of protocol objects and use == operator with your objects as well. For example(I simplified objects a little bit):
let move = MoveCommand(movingVector: .zero, condition: "some")
let rotate = RotateCommand(side: 0, condition: "some")
var array = [Commandable]()
array.append(move)
array.append(rotate)
let equal = (move == MoveCommand(movingVector: .zero, condition: "some"))
let unequal = (move == MoveCommand(movingVector: .zero, condition: "other"))
let unequal = (move == rotate) // can't do this, compare different types
PS. Using var on struct is not a good practice, especially for performance reasons.
I believe the problem here is that the equatable protocol has self requirements. So you can solve you problem by removing equatable protocol from your Commandable protocol and make your your structs equatable instead. This will of course limit your protocol but maybe it is a trade-off that is reasonable?