198 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
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
 | 
						|
    fn hash() -> USize
 | 
						|
end
 | 
						|
 | 
						|
pub int Map<K, V>
 | 
						|
    fn get(key: K) -> Option<&V>
 | 
						|
    fn put(key: K, value: V) -> Void
 | 
						|
    fn take(key: K) -> Option<V>
 | 
						|
end
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
    let mut buckets: List<List<Option<Entry<K, V>>>> = ArrayList(10)
 | 
						|
 | 
						|
    fn getBucketIndex(key: K) -> Int
 | 
						|
        HashCode[K].hash(key) % buckets.size()
 | 
						|
    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
 | 
						|
        let bucket = buckets[getBucketIndex(key)]
 | 
						|
        bucket.add(Entry(key, value))
 | 
						|
        if getCount() / getCapacity() > LOAD_FACTOR then
 | 
						|
            redistribute()
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    impl fn get(key: K) -> Option<&V>
 | 
						|
        let bucket = buckets[getBucketIndex(key)] // bucket: &List<Entry<K, V>>
 | 
						|
        bucket.find { it.key == key } // it: &Entry<K, V>
 | 
						|
            .map { it.value } // it.value: &V
 | 
						|
    end
 | 
						|
 | 
						|
    impl fn take(key: K) -> Option<V>
 | 
						|
        let mut bucket = buckets.take(getBucketIndex(key)) // bucket: List<Entry<K, V>>
 | 
						|
        if bucket.findIndex { it.key == key } is Some(index) then
 | 
						|
            let entry = bucket.take(index) // entry: Entry<K, V>
 | 
						|
            Some(entry.value) // moved out of Entry
 | 
						|
        else
 | 
						|
            None
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
end
 | 
						|
 | 
						|
impl HashCode for String
 | 
						|
    fn hash() -> Int = todo()
 | 
						|
end
 | 
						|
 | 
						|
class Greeter(pub greeting: String) end
 | 
						|
 | 
						|
fn main()
 | 
						|
    let greeterMap: Map<String, Greeter> = HashMap()
 | 
						|
    greeterMap.put("friendly", Greeter("Friendly hello!"))
 | 
						|
    greeterMap.put("nasty", Greeter("Nasty hello!"))
 | 
						|
    let friendlyGreeter: &Greeter = greeterMap.get("friendly").unwrap()
 | 
						|
    println friendlyGreeter.greeting
 | 
						|
    let nastyGreeter: Greeter = greeterMap.take("nasty").unwrap()
 | 
						|
    println nastyGreeter.greeting
 | 
						|
end |