Drop a borrow reference while keeping the underlying allocated memory - memory

Imagine in this case, I basically store data on the heap.
let layout = Layout::new::<usize>();
let data: usize = 1;
let data_ptr = alloc(layout) as *mut usize;
ptr::write(data_ptr, data);
let data_ref = &mut *data_ptr;
Now if I'd like to reuse the same memory to store something else, I can just write another data to data_ptr.
let data2: usize = 2;
ptr::write(data_ptr, data2);
let data2_ref = &mut *data_ptr;
// `data1_ref` is still valid
However, data_ref is still valid under the same scope. How can I invalid data_ref at the language level to make sure it cannot access the allocated memory?

Here's an implementation that I would consider to be fairly idiomatic:
use std::alloc::{alloc, Layout};
struct Wrapper(*mut usize);
impl Wrapper {
fn new() -> Self {
let inner = unsafe { alloc(Layout::new::<usize>()).cast() };
Self(inner)
}
fn write(&mut self, data: usize) {
unsafe { self.0.write(data) }
}
fn as_mut(&mut self) -> &mut usize {
unsafe { &mut *self.0 }
}
}
This ensures that one can not hold on to a ref returned by as_mut after calling write by tying lifetime of &mut usize to the lifetime of self:
fn as_mut(&'a mut self) -> &'a mut usize {
unsafe { &mut *self.0 }
}
Note that if your actual data is more complicated, you have to implement Drop for your wrapper, which can be done like this:
use std::{
alloc::{alloc, dealloc, Layout},
ptr::drop_in_place,
};
struct HasDrop {
// Struct that owns some resources
}
struct Wrapper {
inner: *mut HasDrop,
init: bool,
}
impl Wrapper {
fn new() -> Self {
let inner = unsafe { alloc(Layout::new::<HasDrop>()).cast() };
Self { inner, init: false }
}
fn write(&mut self, data: HasDrop) {
unsafe { self.inner.write(data) }
self.init = true;
}
fn as_mut(&mut self) -> &mut HasDrop {
unsafe { &mut *self.inner }
}
}
impl Drop for Wrapper {
fn drop(&mut self) {
unsafe {
if self.init {
drop_in_place(self.inner);
}
dealloc(self.inner.cast(), Layout::new::<HasDrop>());
}
}
}

Related

Generic parameter 'T' could not be inferred when using a guard statement to unwrap a generic function

I'm trying to use a generic modular function within Combine, but I'm getting the error that generic could not be inferred.
func foo<T>(data: T) -> AnyPublisher<Bool, MyError> {
}
func bar<T>(data: T) -> AnyPublisher<String, MyError> {
Deferred { [weak self] () -> AnyPublisher<Bool, MyError> in
guard let foo = self?.foo else { // error here
return Fail(error: .someError)
.eraseToAnyPublisher()
}
return foo(data)
}
.eraseToAnyPublisher()
.flatMap { [weak self] (value) -> AnyPublisher<String, MyError> in
Future<String, MyError> { [weak self] promise in
// do something with the returned value
promise(.success("Success"))
}
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}
enum MyError: Error {
case someError
}
I'm getting the error when I'm trying to unwrap a function using a guard statement. T doesn't have constraints because it could be multiple disparate types like Data or UIImage which gets type checked within the foo function.
When you have a problem like this, simplify. We can reduce the phenomenon to a very simple case:
class MyClass {
func foo<T>(data: T) -> Void { }
func bar<T>(data: T) -> Void {
let foo = self.foo // error
}
}
Now, the first thing to realize is that you have two separate T placeholders. You say T with regard to foo and with regard to bar, but they have no relation to one another. We can rewrite more clearly:
class MyClass {
func foo<FooDataType>(data: FooDataType) -> Void { }
func bar<BarDataType>(data: BarDataType) -> Void {
let foo = self.foo // error: Generic parameter 'FooDataType' could not be inferred
}
}
Now it's clear what the problem is, because we know which placeholder the compiler is having trouble with. When you look at it that way, you realize that FooDataType is entirely confined to foo. How would bar know what type this is going to be?
If your idea is that they should be the same type, then say so. Make the class the generic, not the individual functions:
class MyClass<T> {
func foo(data: T) -> Void { }
func bar(data: T) -> Void {
let foo = self.foo // fine
}
}

Chain sequence observables with arguments

I'm fairly new to RxSwift, so I have the following problem, lets suppose I have 3 Observable example functions which return different observable types:
func observableFunc1(item1: DummyObject) -> Observable<AVURLAsset> {
return Observable.create { observer in
let something_with_AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: "file"))
observer.onNext(something_with_AVURLAsset)
observer.onCompleted()
return Disposables.create()
}
}
func observableFunc2(item: AVURLAsset) -> Observable<Data> {
return Observable.create { observer in
let something_with_data = Data()
observer.onNext(something_with_data)
observer.onCompleted()
return Disposables.create()
}
}
func observableFunc3(_ params: [String:Any]) -> Observable<Any> {
let disposeBag = DisposeBag()
return Observable.create { observer in
RxAlamofire.request(api.sendData(params)).debug().subscribe(
onNext: { reponse in
observer.onCompleted()
},
onError: { error in
observer.onError(customError.theError("error"))
}
)
.addDisposableTo(disposeBag)
return Disposables.create()
}
}
How can I execute these 3 functions sequentially with the return value of func1 to be used on func2 and then when func2 is completed finally run func3.
I hope I made the question clear enough, but then again I'm really new to RxSwift and I don't know if these operations are possible or not.
Here's an example...
Assuming you have the three functions:
func func1() -> Observable<Data1>
func func2(_ data: Data1) -> Observable<Data2>
func func3(_ data: Data2) -> Observable<Data3>
Then you can:
let a = func1()
let b = a.flatMap { func2($0) }
let c = b.flatMap { func3($0) }
or:
let c = func1()
.flatMap { func2($0) }
.flatMap { func3($0) }
That said, your observableFunc3 is quite broken. You need to remove the dispose bag from it. As it stands, the network call will cancel before it starts.
If you really don't want it to emit any values then:
func observableFunc3(_ params: [String:Any]) -> Observable<Void> {
return RxAlamofire.request(api.sendData(params))
.filter { false }
}
The above will emit either a completed or an error but no next values.
Better would be to write it like:
func observableFunc3(_ params: [String:Any]) -> Observable<Void> {
RxAlamofire.request(api.sendData(params))
.map { _ in }
}
The above will emit one next and then a completed or an error. This is better because you can map or flatMap after it to have things happen once it's done.

Swift Equatable on a protocol

I don't think this can be done but I'll ask anyway. I have a protocol:
protocol X {}
And a class:
class Y:X {}
In the rest of my code I refer to everything using the protocol X. In that code I would like to be able to do something like:
let a:X = ...
let b:X = ...
if a == b {...}
The problem is that if I try to implement Equatable:
protocol X: Equatable {}
func ==(lhs:X, rhs:X) -> Bool {
if let l = lhs as? Y, let r = hrs as? Y {
return l.something == r.something
}
return false
}
The idea to try and allow the use of == whilst hiding the implementations behind the protocol.
Swift doesn't like this though because Equatable has Self references and it will no longer allow me to use it as a type. Only as a generic argument.
So has anyone found a way to apply an operator to a protocol without the protocol becoming unusable as a type?
If you directly implement Equatable on a protocol, it will not longer be usable as a type, which defeats the purpose of using a protocol. Even if you just implement == functions on protocols without Equatable conformance, results can be erroneous. See this post on my blog for a demonstration of these issues:
https://khawerkhaliq.com/blog/swift-protocols-equatable-part-one/
The approach that I have found to work best is to use type erasure. This allows making == comparisons for protocol types (wrapped in type erasers). It is important to note that while we continue to work at the protocol level, the actual == comparisons are delegated to the underlying concrete types to ensure correct results.
I have built a type eraser using your brief example and added some test code at the end. I have added a constant of type String to the protocol and created two conforming types (structs are the easiest for demonstration purposes) to be able to test the various scenarios.
For a detailed explanation of the type erasure methodology used, check out part two of the above blog post:
https://khawerkhaliq.com/blog/swift-protocols-equatable-part-two/
The code below should support the equality comparison that you wanted to implement. You just have to wrap the protocol type in a type eraser instance.
protocol X {
var name: String { get }
func isEqualTo(_ other: X) -> Bool
func asEquatable() -> AnyEquatableX
}
extension X where Self: Equatable {
func isEqualTo(_ other: X) -> Bool {
guard let otherX = other as? Self else { return false }
return self == otherX
}
func asEquatable() -> AnyEquatableX {
return AnyEquatableX(self)
}
}
struct Y: X, Equatable {
let name: String
static func ==(lhs: Y, rhs: Y) -> Bool {
return lhs.name == rhs.name
}
}
struct Z: X, Equatable {
let name: String
static func ==(lhs: Z, rhs: Z) -> Bool {
return lhs.name == rhs.name
}
}
struct AnyEquatableX: X, Equatable {
var name: String { return value.name }
init(_ value: X) { self.value = value }
private let value: X
static func ==(lhs: AnyEquatableX, rhs: AnyEquatableX) -> Bool {
return lhs.value.isEqualTo(rhs.value)
}
}
// instances typed as the protocol
let y: X = Y(name: "My name")
let z: X = Z(name: "My name")
let equalY: X = Y(name: "My name")
let unequalY: X = Y(name: "Your name")
// equality tests
print(y.asEquatable() == z.asEquatable()) // prints false
print(y.asEquatable() == equalY.asEquatable()) // prints true
print(y.asEquatable() == unequalY.asEquatable()) // prints false
Note that since the type eraser conforms to the protocol, you can use instances of the type eraser anywhere an instance of the protocol type is expected.
Hope this helps.
The reason why you should think twice about having a protocol conform to Equatable is that in many cases it just doesn't make sense. Consider this example:
protocol Pet: Equatable {
var age: Int { get }
}
extension Pet {
static func == (lhs: Pet, rhs: Pet) -> Bool {
return lhs.age == rhs.age
}
}
struct Dog: Pet {
let age: Int
let favoriteFood: String
}
struct Cat: Pet {
let age: Int
let favoriteLitter: String
}
let rover: Pet = Dog(age: "1", favoriteFood: "Pizza")
let simba: Pet = Cat(age: "1", favoriteLitter: "Purina")
if rover == simba {
print("Should this be true??")
}
You allude to type checking within the implementation of == but the problem is that you have no information about either of the types beyond them being Pets and you don't know all the things that might be a Pet (maybe you will add a Bird and Rabbit later). If you really need this, another approach can be modeling how languages like C# implement equality, by doing something like:
protocol IsEqual {
func isEqualTo(_ object: Any) -> Bool
}
protocol Pet: IsEqual {
var age: Int { get }
}
struct Dog: Pet {
let age: Int
let favoriteFood: String
func isEqualTo(_ object: Any) -> Bool {
guard let otherDog = object as? Dog else { return false }
return age == otherDog.age && favoriteFood == otherDog.favoriteFood
}
}
struct Cat: Pet {
let age: Int
let favoriteLitter: String
func isEqualTo(_ object: Any) -> Bool {
guard let otherCat = object as? Cat else { return false }
return age == otherCat.age && favoriteLitter == otherCat.favoriteLitter
}
}
let rover: Pet = Dog(age: "1", favoriteFood: "Pizza")
let simba: Pet = Cat(age: "1", favoriteLitter: "Purina")
if !rover.isEqualTo(simba) {
print("That's more like it.")
}
At which point if you really wanted, you could implement == without implementing Equatable:
static func == (lhs: IsEqual, rhs: IsEqual) -> Bool { return lhs.isEqualTo(rhs) }
One thing you would have to watch out for in this case is inheritance though. Because you could downcast an inheriting type and erase the information that might make isEqualTo not make logical sense.
The best way to go though is to only implement equality on the class/struct themselves and use another mechanism for type checking.
Determining equality across conformances to a Swift protocol is possible without type erasure if:
you are willing to forgo the operator syntax (i.e. call isEqual(to:) instead of ==)
you control the protocol (so you can add an isEqual(to:) func to it)
import XCTest
protocol Shape {
func isEqual (to: Shape) -> Bool
}
extension Shape where Self : Equatable {
func isEqual (to: Shape) -> Bool {
return (to as? Self).flatMap({ $0 == self }) ?? false
}
}
struct Circle : Shape, Equatable {
let radius: Double
}
struct Square : Shape, Equatable {
let edge: Double
}
class ProtocolConformanceEquality: XCTestCase {
func test() {
// Does the right thing for same type
XCTAssertTrue(Circle(radius: 1).isEqual(to: Circle(radius: 1)))
XCTAssertFalse(Circle(radius: 1).isEqual(to: Circle(radius: 2)))
// Does the right thing for different types
XCTAssertFalse(Square(edge: 1).isEqual(to: Circle(radius: 1)))
}
}
Any conformances don't conform to Equatable will need to implement isEqual(to:) themselves
maybe this will be helpful for you:
protocol X:Equatable {
var name: String {get set}
}
extension X {
static func ==(lhs: Self, rhs: Self) -> Bool {
return lhs.name == rhs.name
}
}
struct Test : X {
var name: String
}
let first = Test(name: "Test1")
let second = Test(name: "Test2")
print(first == second) // false
All people who say that you can't implement Equatable for a protocol just don't try hard enough. Here is the solution (Swift 4.1) for your protocol X example:
protocol X: Equatable {
var something: Int { get }
}
// Define this operator in the global scope!
func ==<L: X, R: X>(l: L, r: R) -> Bool {
return l.something == r.something
}
And it works!
class Y: X {
var something: Int = 14
}
struct Z: X {
let something: Int = 9
}
let y = Y()
let z = Z()
print(y == z) // false
y.something = z.something
print(y == z) // true
The only problem is that you can't write let a: X = Y() because of "Protocol can only be used as a generic constraint" error.
Not sure why you need all instances of your protocol to conform to Equatable, but I prefer letting classes implement their equality methods.
In this case, I'd leave the protocol simple:
protocol MyProtocol {
func doSomething()
}
If you require that an object that conforms to MyProtocol is also Equatable you can use MyProtocol & Equatable as type constraint:
// Equivalent: func doSomething<T>(element1: T, element2: T) where T: MyProtocol & Equatable {
func doSomething<T: MyProtocol & Equatable>(element1: T, element2: T) {
if element1 == element2 {
element1.doSomething()
}
}
This way you can keep your specification clear and let subclasses implement their equality method only if required.
I would still advise against implementing == using polymorphism. It's a bit of a code smell. If you want to give the framework user something he can test equality with then you should really be vending a struct, not a protocol. That's not to say that it can't be the protocols that are vending the structs though:
struct Info: Equatable {
let a: Int
let b: String
static func == (lhs: Info, rhs: Info) -> Bool {
return lhs.a == rhs.a && lhs.b == rhs.b
}
}
protocol HasInfo {
var info: Info { get }
}
class FirstClass: HasInfo {
/* ... */
}
class SecondClass: HasInfo {
/* ... */
}
let x: HasInfo = FirstClass( /* ... */ )
let y: HasInfo = SecondClass( /* ... */ )
print(x == y) // nope
print(x.info == y.info) // yep
I think this more efficiently communicates your intent, which is basically "you have these things and you don't know if they are the same things, but you do know they have the same set of properties and you can test whether those properties are the same." That is pretty close to how I would implement that Money example.
You have to implement a protocol extension constrained to your class type. Inside that extension you should implement the Equatable operator.
public protocol Protocolable: class, Equatable
{
// Other stuff here...
}
public extension Protocolable where Self: TheClass
{
public static func ==(lhs: Self, rhs:Self) -> Bool
{
return lhs.name == rhs.name
}
}
public class TheClass: Protocolable
{
public var name: String
public init(named name: String)
{
self.name = name
}
}
let aClass: TheClass = TheClass(named: "Cars")
let otherClass: TheClass = TheClass(named: "Wall-E")
if aClass == otherClass
{
print("Equals")
}
else
{
print("Non Equals")
}
But let me recommend you add the operator implementation to your class. Keep It Simple ;-)
Swift 5.1 introduces a new feature into the language called opaque types
Check code below
that still gets back a X, which might be an Y, a Z, or something else that conforms to the X protocol,
but the compiler knows exactly what is being returned
protocol X: Equatable { }
class Y: X {
var something = 3
static func == (lhs: Y, rhs: Y) -> Bool {
return lhs.something == rhs.something
}
static func make() -> some X {
return Y()
}
}
class Z: X {
var something = "5"
static func == (lhs: Z, rhs: Z) -> Bool {
return lhs.something == rhs.something
}
static func make() -> some X {
return Z()
}
}
let a = Z.make()
let b = Z.make()
a == b
I came cross this same issue and I figured that the == operator can be implemented in the global scope (as it used to be), as opposed to a static func inside the protocol's scope:
// This should go in the global scope
public func == (lhs: MyProtocol?, rhs: MyProtocol?) -> Bool { return lhs?.id == rhs?.id }
public func != (lhs: MyProtocol?, rhs: MyProtocol?) -> Bool { return lhs?.id != rhs?.id }
Note that if you use linters such as SwiftLint's static_operator, you'll have to wrap that code around // swiftlint:disable static_operator to silent linter warnings.
Then this code will start compiling:
let obj1: MyProtocol = ConcreteType(id: "1")
let obj2: MyProtocol = ConcreteType(id: "2")
if obj1 == obj2 {
print("They're equal.")
} else {
print("They're not equal.")
}
took some of the code from above and came with the following sollution.
it uses the IsEqual protocol instead of the Equatable protocol and with a few line codes you will be able to compare any two protocol objects with each other, wether they are optional or not, are in an array and even add comparing dates while I was at it.
protocol IsEqual {
func isEqualTo(_ object: Any) -> Bool
}
func == (lhs: IsEqual?, rhs: IsEqual?) -> Bool {
guard let lhs = lhs else { return rhs == nil }
guard let rhs = rhs else { return false }
return lhs.isEqualTo(rhs) }
func == (lhs: [IsEqual]?, rhs: [IsEqual]?) -> Bool {
guard let lhs = lhs else { return rhs == nil }
guard let rhs = rhs else { return false }
guard lhs.count == rhs.count else { return false }
for i in 0..<lhs.count {
if !lhs[i].isEqualTo(rhs[i]) {
return false
}
}
return true
}
func == (lhs: Date?, rhs: Date?) -> Bool {
guard let lhs = lhs else { return rhs == nil }
guard let rhs = rhs else { return false }
return lhs.compare(rhs) == .orderedSame
}
protocol Pet: IsEqual {
var age: Int { get }
}
struct Dog: Pet {
let age: Int
let favoriteFood: String
func isEqualTo(_ object: Any) -> Bool {
guard let otherDog = object as? Dog else { return false }
return age == otherDog.age && favoriteFood == otherDog.favoriteFood
}
}

Swift restrict generic type to Type

How can I restrict a generic type to be a type, not an instance of a type?
If I have a class:
class SomeClass<T: SomeProtocol> {}
how can I ensure that T is only an instance of AnyClass (which is just AnyObject.Type)
My protocol only has static methods and in order to call those methods I have to do instance.dynamicType.protocolMethod whereas I want to do someType.protocolMethod
AFAIK, Swift does not allow you to use a metatype as a generic type. (I believe this is along the lines of what Sam Giddins wished for in Swift 3.)
You can, however, use it as a value. Instead of making T a type parameter, make it a property:
protocol SomeProtocol {
static func foo()
}
struct Concrete: SomeProtocol {
static func foo() {
print("I am concrete")
}
}
class SomeClass {
let T: SomeProtocol.Type
init(T: SomeProtocol.Type) {
self.T = T
}
func go() {
T.foo() // no need for dynamicType
}
}
SomeClass(T: Concrete.self).go()
If, as you say, your protocol contains only static methods, then this is sufficient. However, if you need to tie a generic parameter to the type, that’s possible too:
class SomeClass<U: SomeProtocol> {
let T: U.Type
init(T: U.Type) {
self.T = T
}
func go(value: U) {
T.foo()
}
}
SomeClass(T: Concrete.self).go(Concrete())
protocol P {
static func foo()
}
class A : P {
static func foo() {
print("A class")
}
}
class B : P {
static func foo() {
print("C class")
}
}
var type1 = A.self
var type2 = B.self
func check(cls: AnyClass)->Void {
switch cls {
case is A.Type:
A.foo()
case is B.Type:
B.foo()
default:
break
}
}
check(type1) // A class
check(type2) // C class
let i = Int.self // Int.Type
let ao = AnyObject.self // AnyObject.Protocol
let ac = AnyClass.self // AnyClass.Protocol
let p = P.self // P.Protocol
let f = check.self // (AnyClass)->Void
Edit
protocol P {
static func f()
}
class A : P {
static func f() {
print("A")
}
}
class B : P {
static func f() {
print("B")
}
}
func f(cls: P.Type) {
cls.f()
}
f(A) // A
f(B) // B
class Test<T: P> {
func foo() {
T.f()
}
}
Test<A>().foo() // A
Test<B>().foo() // B

Queue implementation in Swift language

I m trying to implement Queue collection type in Swift platform. I have got some problems about peek, poll and offer functions. When I try to use these functions in my code, it fails. Do you have any advice or true algorithm for that?
import Foundation
class Node<T> {
var value: T? = nil
var next: Node<T>? = nil
var prev: Node<T>? = nil
init() {
}
init(value: T) {
self.value = value
}
}
class Queue<T> {
var count: Int = 0
var head: Node<T> = Node<T>()
var tail: Node<T> = Node<T>()
var currentNode : Node<T> = Node<T>()
init() {
}
func isEmpty() -> Bool {
return self.count == 0
}
func next(index:Int) -> T? {
if isEmpty() {
return nil
} else if self.count == 1 {
var temp: Node<T> = currentNode
return temp.value
} else if index == self.count{
return currentNode.value
}else {
var temp: Node<T> = currentNode
currentNode = currentNode.next!
return temp.value
}
}
func setCurrentNode(){
currentNode = head
}
func enQueue(key: T) {
var node = Node<T>(value: key)
if self.isEmpty() {
self.head = node
self.tail = node
} else {
node.next = self.head
self.head.prev = node
self.head = node
}
self.count++
}
func deQueue() -> T? {
if self.isEmpty() {
return nil
} else if self.count == 1 {
var temp: Node<T> = self.tail
self.count--
return temp.value
} else {
var temp: Node<T> = self.tail
self.tail = self.tail.prev!
self.count--
return temp.value
}
}
//retrieve the top most item
func peek() -> T? {
if isEmpty() {
return nil
}
return head.value!
}
func poll() -> T? {
if isEmpty() {
return nil
}else{
var temp:T = head.value!
deQueue()
return temp
}
}
func offer(var key:T)->Bool{
var status:Bool = false;
self.enQueue(key)
status = true
return status
}
}
Aside from the bugs, there are a couple of things about your implementation that you probably want to change to make it more Swift-like. One is it looks like you're replicating the Java names like poll and offer – these names are (IMHO) a little strange, and partly related to needing to have two functions, an exception-throwing version and a non-exception version. Since Swift doesn't have exceptions, you can probably just name them using the conventional names other Swift collections use, like append.
The other issue is that your implementation incorporates traversing the queue into the queue itself. It's better to do this kind of traversal outside the collection than mix the two. Swift collections do this with indexes.
Here's a possible Swift-like queue implementation. First, the node and base queue definition:
// singly rather than doubly linked list implementation
// private, as users of Queue never use this directly
private final class QueueNode<T> {
// note, not optional – every node has a value
var value: T
// but the last node doesn't have a next
var next: QueueNode<T>? = nil
init(value: T) { self.value = value }
}
// Ideally, Queue would be a struct with value semantics but
// I'll leave that for now
public final class Queue<T> {
// note, these are both optionals, to handle
// an empty queue
private var head: QueueNode<T>? = nil
private var tail: QueueNode<T>? = nil
public init() { }
}
Then, extend with an append and dequeue method:
extension Queue {
// append is the standard name in Swift for this operation
public func append(newElement: T) {
let oldTail = tail
self.tail = QueueNode(value: newElement)
if head == nil { head = tail }
else { oldTail?.next = self.tail }
}
public func dequeue() -> T? {
if let head = self.head {
self.head = head.next
if head.next == nil { tail = nil }
return head.value
}
else {
return nil
}
}
}
At this point, you're almost done if all you want to do is add and remove. To add traversal, first create an index type, which is a simple wrapper on the node type:
public struct QueueIndex<T>: ForwardIndexType {
private let node: QueueNode<T>?
public func successor() -> QueueIndex<T> {
return QueueIndex(node: node?.next)
}
}
public func ==<T>(lhs: QueueIndex<T>, rhs: QueueIndex<T>) -> Bool {
return lhs.node === rhs.node
}
Then, use this index to conform to MutableCollectionType:
extension Queue: MutableCollectionType {
public typealias Index = QueueIndex<T>
public var startIndex: Index { return Index(node: head) }
public var endIndex: Index { return Index(node: nil) }
public subscript(idx: Index) -> T {
get {
precondition(idx.node != nil, "Attempt to subscript out of bounds")
return idx.node!.value
}
set(newValue) {
precondition(idx.node != nil, "Attempt to subscript out of bounds")
idx.node!.value = newValue
}
}
typealias Generator = IndexingGenerator<Queue>
public func generate() -> Generator {
return Generator(self)
}
}
From conforming to collection type, you get a whole load of stuff for free:
var q = Queue<String>()
q.append("one")
q.append("two")
for x in q {
println(x)
}
isEmpty(q) // returns false
first(q) // returns Optional("one")
count(q) // returns 2
",".join(q) // returns "one,two"
let x = find(q, "two") // returns index of second entry
let counts = map(q) { count($0) } // returns [3,3]
Finally, there's 3 more protocols that are good to conform to: ExtensibleCollectionType, Printable and ArrayLiteralConvertible:
// init() and append() requirements are already covered
extension Queue: ExtensibleCollectionType {
public func reserveCapacity(n: Index.Distance) {
// do nothing
}
public func extend<S : SequenceType where S.Generator.Element == T>
(newElements: S) {
for x in newElements {
self.append(x)
}
}
}
extension Queue: ArrayLiteralConvertible {
public convenience init(arrayLiteral elements: T...) {
self.init()
// conformance to ExtensibleCollectionType makes this easy
self.extend(elements)
}
}
extension Queue: Printable {
// pretty easy given conformance to CollectionType
public var description: String {
return "[" + ", ".join(map(self,toString)) + "]"
}
}
These mean you can now create queues as easily arrays or sets:
var q: Queue = [1,2,3]
println(q) // prints [1, 2, 3]
There are a lot of little issues regarding the internal consistency of your model:
When you first instantiate a new Queue, you are initializing head, tail and current to three different Node objects (even though nothing's been queued yet!). That doesn't make sense. Personally, I'd be inclined to make those three properties optional and leave them as nil until you start enqueuing stuff.
By the way, when you start using optionals for these properties, many of the other methods are simplified.
It looks like you're trying to implement a doubly linked list. So, when you dequeue, you need to not only update the Queue properties, but you also need to update the next pointer for the next item that will be dequeued (because it still will be pointing to that item you already dequeued). You don't want your linked list maintaining references to objects that have been dequeued and should be removed.
When you dequeue the last item, you really should be clearing out head and tail references.
You're implementing a doubly linked list, without regard to the object ownership model. Thus, as soon as you have more than one item in your list, you've got a strong reference cycle between nodes and if not remedied, this will leak if there are still objects in the queue when the queue, itself, is deallocated. Consider making one of the references weak or unowned.
I'd suggest keeping this simple (just enqueue and dequeue). The concept of poll and offer may make sense in terms of an arbitrary linked list, but not in the context of a queue. The implementations of poll and offer are also incorrect (e.g. poll calls deQueue which removes the tail, but the object you return is the head!), but I presume you'd just remove these functions altogether. Likewise, I do not understand the intent of current in the context of a queue.
I'd suggest you make Queue and Node conform to Printable. It will simplify your debugging process.
The following is code of a playground consisting of a queue implemented with an array and a queue implemented with nodes. There are substantial performance differences between the two but if you going to be iterating through a queue you might want to use one with an array.
import UIKit // for NSDate() used in testing)
// QUEUE WITH ARRAY IMPLEMENTATION (For ease of adaptibility, slow enque, faster deque):
struct QueueArray<T> {
private var items = [T]()
mutating func enQueue(item: T) {
items.append(item)
}
mutating func deQueue() -> T? {
return items.removeFirst()
}
func isEmpty() -> Bool {
return items.isEmpty
}
func peek() -> T? {
return items.first
}
}
// QUEUE WITH NODE IMPLEMENTATION (For performance, if all you need is a queue this is it):
class QNode<T> {
var value: T
var next: QNode?
init(item:T) {
value = item
}
}
struct Queue<T> {
private var top: QNode<T>!
private var bottom: QNode<T>!
init() {
top = nil
bottom = nil
}
mutating func enQueue(item: T) {
let newNode:QNode<T> = QNode(item: item)
if top == nil {
top = newNode
bottom = top
return
}
bottom.next = newNode
bottom = newNode
}
mutating func deQueue() -> T? {
let topItem: T? = top?.value
if topItem == nil {
return nil
}
if let nextItem = top.next {
top = nextItem
} else {
top = nil
bottom = nil
}
return topItem
}
func isEmpty() -> Bool {
return top == nil ? true : false
}
func peek() -> T? {
return top?.value
}
}
// QUEUE NODES TEST
let testAmount = 100
var queueNodes = Queue<Int>()
let queueNodesEnqueStart = NSDate()
for i in 0...testAmount {
queueNodes.enQueue(i)
}
let queueNodesEnqueEnd = NSDate()
while !queueNodes.isEmpty() {
queueNodes.deQueue()
}
let queueNodesDequeEnd = NSDate()
// QUEUE ARRAY TEST
var queueArray = QueueArray<Int>()
let queueArrayEnqueStart = NSDate()
for i in 0...testAmount {
queueArray.enQueue(i)
}
let queueArrayEnqueEnd = NSDate()
while !queueArray.isEmpty() {
queueArray.deQueue()
}
let queueArrayDequeEnd = NSDate()
// QUEUE NODES RESULT:
print("queueEnqueDuration: \(queueNodesEnqueEnd.timeIntervalSinceDate(queueNodesEnqueStart)), Deque: \(queueNodesDequeEnd.timeIntervalSinceDate(queueNodesEnqueEnd))")
// QUEUE ARRAY RESULT:
print("queueArrayEnqueDuration: \(queueArrayEnqueEnd.timeIntervalSinceDate(queueArrayEnqueStart)), Deque: \(queueArrayDequeEnd.timeIntervalSinceDate(queueArrayEnqueEnd))")
Queue with Array
struct Queue<T> {
private var list = [T]()
var isEmpty: Bool { return self.list.isEmpty }
var front: T? { return self.list.first }
mutating func enqueue(_ item: T) {
self.list.append(item)
}
mutating func dequeue() -> T? {
guard self.isEmpty == false else { return nil }
return self.list.removeFirst()
}
}
Swift 4 simple Stack for any type; string, int, array, etc.
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
mutating func peek() -> Element {
return items.last!
}
mutating func pushFirst(_ item: Element) {
items.insert(item, at: 0)
}
}
example with strings:
let names = ["Bob", "Sam", "Sue", "Greg", "Brian", "Dave"]
//create stack of string type
var stackOfStrings = Stack<String>()
//add to bottom of stack
for stringName in names {
stackOfStrings.push(stringName)
}
//print and remove from stack
for stringName in names {
print(stringName)
stackOfStrings.pop(stringName)
}
//add to top of stack
for stringName in names {
stackOfStrings.pushFirst(stringName)
}
//look at item in stack without pop
for stringName in names {
//see what Top item is without remove
let whatIsTopItem = stackOfStrings.peek(stringName)
if whatIsTopItem == "Bob" {
print("Best friend Bob is in town!")
}
}
//stack size
let stackCount = stackOfStrings.items.count
more info here:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html

Resources