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 | 
