Skip to content

Instantly share code, notes, and snippets.

@Rivukis
Last active December 13, 2016 17:49
Show Gist options
  • Save Rivukis/46c4ac1195fc546c97b7f706640727f9 to your computer and use it in GitHub Desktop.
Save Rivukis/46c4ac1195fc546c97b7f706640727f9 to your computer and use it in GitHub Desktop.
// MARK: Equatable
func ==<T>(lhs: TerminatingNode<T>, rhs: TerminatingNode<T>) -> Bool {
return lhs.value == rhs.value
}
func ==<T, U>(lhs: ListNode<T, U>, rhs: ListNode<T, U>) -> Bool {
return lhs.value == rhs.value && lhs.next == rhs.next
}
// MARK: Heterogeneous Linked List
protocol NodeType: Equatable {
associatedtype ValueType: Equatable
var value: ValueType { get }
}
struct TerminatingNode<ValueType: Equatable>: NodeType {
let value: ValueType
}
struct ListNode<ValueType: Equatable, NextNodeType: NodeType>: NodeType {
let value: ValueType
let next: NextNodeType
}
// MARK: normal '.value' Tests
let a = TerminatingNode(value: 123)
var b = ListNode(value: 456, next: a)
var c = ListNode(value: "asdf", next: b)
assert(c.value == "asdf")
assert(c.next.value == 456)
assert(c.next.next.value == 123)
assert(type(of:c.value) == String.self)
assert(type(of:c.next.value) == Int.self)
// MARK: Infix Operator
extension NodeType {
func prepend<U>(value: U) -> ListNode<U, Self> {
return ListNode(value: value, next: self)
}
}
precedencegroup ListInfixPrecedence {
associativity: right
}
infix operator >>> : ListInfixPrecedence
func >>><T, U: NodeType>(lhs: T, rhs: U) -> ListNode<T, U> {
return ListNode(value: lhs, next: rhs)
}
func >>><T, U>(lhs: T, rhs: U) -> ListNode<T, TerminatingNode<U>> {
return TerminatingNode(value: rhs).prepend(value: lhs)
}
// MARK: infix '.value' Tests
let list = "asdf" >>> 456 >>> 123
assert(list.value == c.value)
assert(list.next.value == c.next.value)
assert(list.next.next.value == c.next.next.value)
// MARK: prefix operator
prefix operator >>>
// MARK: TerminatingNode Equality Tests
let termInt = TerminatingNode(value: 123)
let termIntSame = TerminatingNode(value: 123)
let termIntDifferent = TerminatingNode(value: 456)
let termStr = TerminatingNode(value: "asdf")
//assert(!termInt == termStr) // wrong types
assert(termInt != termIntDifferent) // correct types, wrong value
assert(termInt == termIntSame) // correct types, correct value
// MARK: Node Equality Tests
let a1 = TerminatingNode(value: 123)
var b1 = ListNode(value: 456, next: a1)
var c1 = ListNode(value: "asdf", next: b1)
let a2 = TerminatingNode(value: 123)
var b2 = ListNode(value: 456, next: a2)
var c2 = ListNode(value: "asdf", next: b2)
assert(a1 == a2) // 123 == 123
assert(b1 == b2) // 456 -> 123 == 456 -> 123
assert(c1 == c2) // asdf -> 456 -> 123 == asdf -> 456 -> 123
let a3 = TerminatingNode(value: 123)
var b3 = ListNode(value: 12356789, next: a3)
var c3 = ListNode(value: "asdf", next: b3)
assert(a1 == a3) // 123 == 123
assert(b1 != b3) // 456 -> 123 != 123456789 -> 123
assert(c1 != c3) // asdf -> 456 -> 123 != asdf -> 123456789 -> 123
let list1 = 123 >>> "asdf" >>> 456
let list2 = 123 >>> "asdf" >>> 456
let list3 = 123 >>> "asdfasdf" >>> 456
let list4 = 123 >>> "sdf" >>> 345 >>> 234
assert(list1 == list2)
assert(list1 != list3)
//assert(list1 != list4) // wrong types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment