|
"A record type, mapping a list of key types |
|
to values. The type parameter [[U]] is a |
|
union of key types." |
|
sealed shared interface Record<U> { |
|
//TODO: should really be contravariant, |
|
// but there is a limitation in |
|
// Ceylon's type arg inference that |
|
// makes this impossible |
|
shared formal I get<I>(Key<U,I> key); |
|
} |
|
|
|
"A key to an element in a [[Record]]. Keys |
|
are singleton classes that extend this |
|
class. The type parameter [[K]] encodes |
|
the type of the key. The type parameter |
|
[[I]] encodes the type of the keyed item." |
|
abstract shared class Key<out K,I>() of K |
|
given K satisfies Key<K,I> {} |
|
|
|
"An empty [[Record]]." |
|
shared Record<Nothing> emptyRecord |
|
= EmptyRecord.instance; |
|
|
|
"Create a record, given a [[key]] and [[item]] |
|
and an existing [[record]]." |
|
shared Record<U|K> record<U,K,I> |
|
(Record<U> record, Key<K,I> key, I item) |
|
given K satisfies Key<K,I> |
|
=> ConsedRecord(record, key,item); |
|
|
|
|
|
//INTERNAL IMPLEMENTATION |
|
|
|
"An empty [[Record]]." |
|
class EmptyRecord |
|
satisfies Record<Nothing> { |
|
shared actual I get<I>(Key<Nothing,I> key) { |
|
assert (false); |
|
} |
|
shared new instance {} |
|
} |
|
|
|
"A [[Record]] composed of a key/item pair |
|
and another record." |
|
class ConsedRecord<U,K,T> |
|
(Record<U> record, Key<K,T> key, T item) |
|
satisfies Record<U|K> |
|
given K satisfies Key<K,T> { |
|
|
|
shared actual I get<I>(Key<U|K,I> key) { |
|
if (key==this.key) { |
|
assert (is I item = this.item); |
|
return item; |
|
} |
|
else if (is Key<U,I> key) { |
|
return record.get(key); |
|
} |
|
else { |
|
assert (false); |
|
} |
|
} |
|
|
|
} |
Click here to run this code online