Last active
December 13, 2016 17:49
-
-
Save Rivukis/46c4ac1195fc546c97b7f706640727f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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