Added std::set::Set

This type is a hash set implemented using a Map of boolean values.
parent 1a65f83f
......@@ -608,7 +608,7 @@ impl Length for Map!(K, V) {
#
# Using a map with one key-value pair:
#
# let mut map = Map.new
# let map = Map.new
#
# map['name'] = 'Alice'
#
......
# A hash set implemented using a Map.
import std::format::(self, Formatter, Inspect)
import std::hash::Hash
import std::iterator::Iterator
import std::length::Length
import std::operators::Equal
# A hash set implemented using a Map.
#
# The order of values in this Set are not guaranteed. For values to be stored in
# a `Set` they must implement the `Hash` and `Equal` traits.
object Set!(V: Hash + Equal) {
# The Map used for storing values.
#
# The keys are the values inserted in this `Set`, the values are always set to
# `True`.
@map: Map!(V, Boolean)
def init {
@map = Map.new
}
# Inserts a new value into the `Set`.
#
# The returned value is `True` if the value was inserted, `False` otherwise.
#
# # Examples
#
# Inserting a value into a `Set`:
#
# import std::set::Set
#
# let set = Set.new
#
# set.insert(10)
def insert(value: V) -> Boolean {
@map[value].if(true: { False }, false: { @map[value] = True })
}
# Removes a value from this `Set`.
#
# If the value was removed `True` is returned, otherwise `False` is returned.
#
# # Examples
#
# Removing an existing value from a `Set`:
#
# import std::set::Set
#
# let set = Set.new
#
# set.insert(10)
# set.remove(10) # => True
# set.remove(10) # => False
#
# Removing a non-existing value from a `Set`:
#
# import std::set::Set
#
# let set = Set.new
#
# set.remove(10) # => False
def remove(value: V) -> ?V {
@map.remove(value).not_nil?
}
# Calls the supplied `Block` for every value in this `Set`.
#
# # Examples
#
# Iterating over the values in a `Set`:
#
# import std::set::Set
#
# let set = Set.new
#
# set.insert(10)
# set.insert(20)
#
# set.each do (value) {
# value # => 10, 20
# }
def each(block: do (V)) {
@map.each do (key, _) {
block.call(key)
}
}
# Returns an `Iterator` over the values in this `Set`.
#
# # Examples
#
# Creating an `Iterator` for the values:
#
# import std::set::Set
#
# let set = Set.new
#
# set.insert(10)
# set.insert(20)
#
# set.iter.next # => 10
def iter -> Iterator!(V) {
@map.keys
}
# Returns `True` if this `Set` contains the given value.
#
# # Examples
#
# Checking if a `Set` contains a value:
#
# import std::set::Set
#
# let set = Set.new
#
# set.contains?(10) # => False
# set.insert(10)
# set.contains?(10) # => True
def contains?(value: V) -> Boolean {
@map.key?(value)
}
}
impl Equal for Set!(V) {
# Returns `True` if `self` and the given `Set` are identical to each
# other.
#
# # Examples
#
# Comparing two `Set` instances:
#
# import std::set::Set
#
# let set1 = Set.new
# let set2 = Set.new
#
# set1.insert(10)
# set2.insert(10)
#
# set1 == set2 # => True
def ==(other: Self) -> Boolean {
(length == other.length).if_false {
return False
}
each do (value) {
other.contains?(value).if_false {
return False
}
}
True
}
}
impl Length for Set!(V) {
# Returns the number of values in this `Set`.
#
# # Examples
#
# Using an empty `Set`:
#
# import std::set::Set
#
# Set.new.length # => 0
#
# Using a `Set` with one value:
#
# let set = Set.new
#
# set.insert('Alice')
#
# set.length # => 1
def length -> Integer {
@map.length
}
}
impl Inspect for Set!(V) {
# Returns a human-readable representation of this `Set`.
#
# # Examples
#
# Inspecting a `Set`:
#
# let set = Set.new
#
# set.insert('Alice')
# set.insert('Foo Street')
#
# set.inspect # => 'Set { "Alice", "Foo Street" }'
def inspect -> String where V: Inspect {
::format.inspect(self)
}
# Formats this `Set` into a human-readable representation.
def format_for_inspect(formatter: Formatter) where V: Inspect {
let last = length - 1
let mut index = 0
formatter.push('Set')
empty?.if_true {
return
}
formatter.push(' { ')
each do (value) {
formatter.descend {
value.format_for_inspect(formatter)
}
(index < last).if_true {
formatter.push(', ')
}
index += 1
}
formatter.push(' }')
}
}
......@@ -35,11 +35,11 @@ import test::std::test_ffi
import test::std::test_float
import test::std::test_format
import test::std::test_fs
import test::std::test_map
import test::std::test_integer
import test::std::test_io
import test::std::test_iterator
import test::std::test_length
import test::std::test_map
import test::std::test_mirror
import test::std::test_nil
import test::std::test_object
......@@ -48,6 +48,7 @@ import test::std::test_pair
import test::std::test_process
import test::std::test_random
import test::std::test_range
import test::std::test_set
import test::std::test_string
import test::std::test_string_buffer
import test::std::test_time
......
import std::set::Set
import std::test
import std::test::assert
test.group('std::set::Set.insert') do (g) {
g.test('Inserting a value into a Set') {
let set = Set.new
assert.true(set.insert(10))
assert.false(set.insert(10))
}
}
test.group('std::set::Set.remove') do (g) {
g.test('Removing a non-existing value from a Set') {
let set = Set.new
assert.false(set.remove(10))
}
g.test('Removing an existing value from a Set') {
let set = Set.new
set.insert(10)
assert.true(set.remove(10))
}
}
test.group('std::set::Set.each') do (g) {
g.test('Iterating over the values in a Set') {
let set = Set.new
let mut total = 0
set.insert(1)
set.insert(2)
set.each do (value) {
total += value
}
assert.equal(total, 3)
}
}
test.group('std::set::Set.iter') do (g) {
g.test('Iterating over the values in a Set') {
let set = Set.new
set.insert(1)
let iter = set.iter
assert.equal(iter.next, 1)
assert.equal(iter.next, Nil)
}
}
test.group('std::set::Set.contains?') do (g) {
g.test('Checking if a Set contains a value') {
let set = Set.new
assert.false(set.contains?(10))
set.insert(10)
assert.true(set.contains?(10))
}
}
test.group('std::set::Set.==') do (g) {
g.test('Checking if two Sets are equal') {
let set1 = Set.new
let set2 = Set.new
let set3 = Set.new
set1.insert(1)
set2.insert(1)
set3.insert(2)
assert.equal(set1, set2)
assert.not_equal(set1, set3)
}
}
test.group('std::set::Set.length') do (g) {
g.test('Obtaining the numer of values in a Set') {
let set = Set.new
assert.equal(set.length, 0)
set.insert(1)
set.insert(2)
assert.equal(set.length, 2)
}
}
test.group('std::set::Set.inspect') do (g) {
g.test('Inspecting an empty Set') {
assert.equal(Set.new.inspect, 'Set')
}
g.test('Inspecting a Set with a single value') {
let set = Set.new
set.insert(1)
assert.equal(set.inspect, 'Set { 1 }')
}
g.test('Inspecting a Set with multiple values') {
let set = Set.new
set.insert(1)
set.insert(2)
let output = set.inspect
let valid = (output == 'Set { 1, 2 }').or { output == 'Set { 2, 1 }' }
assert.true(valid)
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment