Work on Map sketching and related.
This commit is contained in:
parent
5f1233a393
commit
0d2db659ca
@ -1,3 +1,120 @@
|
|||||||
|
pub trait Functor<T>[Self<T>]
|
||||||
|
fn map(mapper: fn (t: &T) -> U) -> Self<U>
|
||||||
|
end
|
||||||
|
|
||||||
|
pub trait Sum<T>
|
||||||
|
fn sum() -> T
|
||||||
|
end
|
||||||
|
|
||||||
|
pub trait Default
|
||||||
|
fn default() -> Self
|
||||||
|
end
|
||||||
|
|
||||||
|
pub trait Iter<T>
|
||||||
|
ref fn iter() -> Iterator<&T>
|
||||||
|
end
|
||||||
|
|
||||||
|
pub trait ConsIter<T>
|
||||||
|
cons fn consIter() -> Iterator<T>
|
||||||
|
end
|
||||||
|
|
||||||
|
pub int Iterator<T>
|
||||||
|
fn next() -> Option<T>
|
||||||
|
end
|
||||||
|
|
||||||
|
pub int List<T> impl Functor<T>, Iter<T>, ConsIter<T>
|
||||||
|
fn add(t: T) -> Void
|
||||||
|
end
|
||||||
|
|
||||||
|
pub class ArrayList<T> : List<T>
|
||||||
|
let mut currentIndex = 0
|
||||||
|
let mut inner: Array<T>
|
||||||
|
|
||||||
|
ctor(capacity: Int) where T impl Default
|
||||||
|
inner = Array(capacity, Default[T])
|
||||||
|
end
|
||||||
|
|
||||||
|
ctor(capacity: Int, init: fn () -> T)
|
||||||
|
inner = Array(capacity, init)
|
||||||
|
end
|
||||||
|
|
||||||
|
impl fn add(t: T) -> Void
|
||||||
|
inner[currentIndex] = t
|
||||||
|
let currentCapacity = inner.capacity()
|
||||||
|
currentIndex++
|
||||||
|
if currentIndex == currentCapacity then
|
||||||
|
let oldInner = std::mem::take(inner, Array(currentCapacity * 2))
|
||||||
|
arrays::copy(oldInner, inner)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl Functor[ArrayList<*>]
|
||||||
|
fn map(mapper: fn (t: &T) -> U) -> Self<U>
|
||||||
|
let mut result: Array<U> = Array(inner.capacity)
|
||||||
|
for (i, t) in inner.iterWithIndex() do
|
||||||
|
result[i] = mapper(t)
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl Sum[Self = List<Int>, T = Int]
|
||||||
|
fn sum() -> Int
|
||||||
|
let mut result = 0
|
||||||
|
for value in self do
|
||||||
|
result += value
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T impl Default> Default[ArrayList<T>]
|
||||||
|
const DEFAULT_SIZE = 10
|
||||||
|
|
||||||
|
static fn default() -> Self = ArrayList(DEFAULT_SIZE, Default[T]::default)
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T> Iter[ArrayList<T>]
|
||||||
|
ref fn iter() -> Iterator<&T>
|
||||||
|
let mut currentIndex = 0
|
||||||
|
return {
|
||||||
|
if currentIndex < inner.count() then
|
||||||
|
let item = inner[currentIndex]
|
||||||
|
currentIndex++
|
||||||
|
Some(item)
|
||||||
|
else
|
||||||
|
None
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T impl Default> ConsIter[ArrayList<T>]
|
||||||
|
cons fn consIter() -> Iterator<T>
|
||||||
|
let mut currentIndex = 0
|
||||||
|
let inner = std::mem::take(inner, std::arrays::empty())
|
||||||
|
return |inner| {
|
||||||
|
if currentIndex < inner.count() then
|
||||||
|
let item = inner.take(currentIndex, Default[T]::default)
|
||||||
|
currentIndex++
|
||||||
|
Some(item)
|
||||||
|
else
|
||||||
|
None
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pub enum Option<T>
|
||||||
|
Some(t: T),
|
||||||
|
None
|
||||||
|
end
|
||||||
|
|
||||||
|
impl Default[Option<*>]
|
||||||
|
static fn default() -> Self = None
|
||||||
|
end
|
||||||
|
|
||||||
pub trait HashCode
|
pub trait HashCode
|
||||||
fn hash() -> USize
|
fn hash() -> USize
|
||||||
end
|
end
|
||||||
@ -8,37 +125,60 @@ pub int Map<K, V>
|
|||||||
fn take(key: K) -> Option<V>
|
fn take(key: K) -> Option<V>
|
||||||
end
|
end
|
||||||
|
|
||||||
pub class HashMap<K, V>(hasher: impl HashCode[K]) : Map<K, V>
|
pub class HashMap<K, V> : Map<K, V>
|
||||||
|
where K impl HashCode
|
||||||
|
|
||||||
|
const LOAD_FACTOR = 0.8
|
||||||
|
|
||||||
class Entry<K, V>(pub key: K, pub value: V) end
|
class Entry<K, V>(pub key: K, pub value: V) end
|
||||||
|
|
||||||
let mut buckets: List<List<Entry<K, V>>> = ArrayList(size: 10, init: { [] })
|
let mut buckets: List<List<Option<Entry<K, V>>>> = ArrayList(10)
|
||||||
|
|
||||||
fn getBucketIndex(key: K) -> Int
|
fn getBucketIndex(key: K) -> Int
|
||||||
hasher.hash(key) & buckets.size()
|
HashCode[K].hash(key) % buckets.size()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
fn getCount() -> Int = buckets.map { it.count() }.sum::<Int>()
|
||||||
|
|
||||||
|
fn getCapacity() -> Int = buckets.map { it.capacity() }.sum::<Int>()
|
||||||
|
|
||||||
|
fn redistribute()
|
||||||
|
use std::mem::take
|
||||||
|
let oldBucketCapacity = buckets.first().unwrap().capacity()
|
||||||
|
let oldBuckets = take(buckets, ArrayList(oldBucketCapacity * 2))
|
||||||
|
for bucket in oldBuckets.consIter() do
|
||||||
|
for entry in bucket.consIter() do
|
||||||
|
let newIndex = getBucketIndex(entry.key)
|
||||||
|
let newBucket = buckets[newIndex]
|
||||||
|
newBucket.add(Entry(entry.key, entry.value))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
impl fn put(key: K, value: V) -> Void
|
impl fn put(key: K, value: V) -> Void
|
||||||
let bucket = buckets[getBucketIndex(key)]
|
let bucket = buckets[getBucketIndex(key)]
|
||||||
bucket.add(Entry(key, value))
|
bucket.add(Entry(key, value))
|
||||||
|
if getCount() / getCapacity() > LOAD_FACTOR then
|
||||||
|
redistribute()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
impl fn get(key: K) -> Option<&V>
|
impl fn get(key: K) -> Option<&V>
|
||||||
let bucket = buckets[getBucketIndex(key)] // bucket: &List<Entry<K, V>>
|
let bucket = buckets[getBucketIndex(key)] // bucket: &List<Entry<K, V>>
|
||||||
bucket.find { it.key == key } // it: &Entry<K, V>
|
bucket.find { it.key == key } // it: &Entry<K, V>
|
||||||
.map { it.value } // it.value: &V
|
.map { it.value } // it.value: &V
|
||||||
end
|
end
|
||||||
|
|
||||||
impl fn take(key: K) -> Option<V>
|
impl fn take(key: K) -> Option<V>
|
||||||
let mut bucket = buckets.take(getBucketIndex(key), []) // bucket: List<Entry<K, V>>
|
let mut bucket = buckets.take(getBucketIndex(key)) // bucket: List<Entry<K, V>>
|
||||||
if bucket.findIndex { it.key == key } is Some(index) then
|
if bucket.findIndex { it.key == key } is Some(index) then
|
||||||
let entry = bucket.remove(index) // entry: Entry<K, V>
|
let entry = bucket.take(index) // entry: Entry<K, V>
|
||||||
Some(entry.value) // moved out of Entry
|
Some(entry.value) // moved out of Entry
|
||||||
else
|
else
|
||||||
None
|
None
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
impl HashCode for String
|
impl HashCode for String
|
||||||
@ -48,7 +188,7 @@ end
|
|||||||
class Greeter(pub greeting: String) end
|
class Greeter(pub greeting: String) end
|
||||||
|
|
||||||
fn main()
|
fn main()
|
||||||
let greeterMap: Map<String, Greeter> = HashMap(HashCode[]) // Short for HashCode[String]
|
let greeterMap: Map<String, Greeter> = HashMap()
|
||||||
greeterMap.put("friendly", Greeter("Friendly hello!"))
|
greeterMap.put("friendly", Greeter("Friendly hello!"))
|
||||||
greeterMap.put("nasty", Greeter("Nasty hello!"))
|
greeterMap.put("nasty", Greeter("Nasty hello!"))
|
||||||
let friendlyGreeter: &Greeter = greeterMap.get("friendly").unwrap()
|
let friendlyGreeter: &Greeter = greeterMap.get("friendly").unwrap()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user