This commit is contained in:
lx
2026-07-06 14:01:11 -04:00
commit c4f97d729d
16468 changed files with 935321 additions and 0 deletions
@@ -0,0 +1,12 @@
--[[
Defines utilities for working with 'dictionary-like' tables.
Dictionaries can be indexed by any value, but don't have the ordering
expectations that lists have.
]]
return {
join = require(script.join),
keys = require(script.keys),
values = require(script.values),
}
@@ -0,0 +1,5 @@
return function()
it("should load", function()
require(script.Parent)
end)
end
@@ -0,0 +1,30 @@
local None = require(script.Parent.Parent.None)
--[[
Combine a number of dictionary-like tables into a new table.
Keys specified in later tables will overwrite keys in previous tables.
Use `Cryo.None` as a value to remove a key. This is necessary because
Lua does not distinguish between a value not being present in a table and a
value being `nil`.
]]
local function join(...)
local new = {}
for i = 1, select("#", ...) do
local source = select(i, ...)
for key, value in pairs(source) do
if value == None then
new[key] = nil
else
new[key] = value
end
end
end
return new
end
return join
@@ -0,0 +1,94 @@
return function()
local join = require(script.Parent.join)
local None = require(script.Parent.Parent.None)
it("should return a new table", function()
local a = {}
expect(join(a)).never.to.equal(a)
end)
it("should merge tables, overwriting previous values", function()
local a = {
foo = "foo-a",
bar = "bar-a",
}
local b = {
foo = "foo-b",
baz = "baz-b",
}
local c = join(a, b)
expect(c.foo).to.equal(b.foo)
expect(c.bar).to.equal(a.bar)
expect(c.baz).to.equal(b.baz)
end)
it("should remove values set to None", function()
local a = {
foo = "foo-a",
}
local b = {
foo = None,
}
local c = join(a, b)
expect(c.foo).to.equal(nil)
end)
it("should not mutate passed in tables", function()
local mutationsA = 0
local mutationsB = 0
local a = {}
local b = {
foo = "foo-b",
}
setmetatable(a, {
__newindex = function()
mutationsA = mutationsA + 1
end,
})
setmetatable(b, {
__newindex = function()
mutationsB = mutationsB + 1
end,
})
join(a, b)
expect(mutationsA).to.equal(0)
expect(mutationsB).to.equal(0)
expect(b.foo).to.equal("foo-b")
end)
it("should accept arbitrary numbers of tables", function()
local a = {
foo = "foo-a",
}
local b = {
bar = "bar-b",
}
local c = {
baz = "baz-c",
}
local d = join(a, b, c)
expect(d.foo).to.equal(a.foo)
expect(d.bar).to.equal(b.bar)
expect(d.baz).to.equal(c.baz)
end)
it("should accept zero tables", function()
expect(join()).to.be.a("table")
end)
end
@@ -0,0 +1,16 @@
--[[
Returns a list of the keys from the given dictionary.
]]
local function keys(dictionary)
local new = {}
local index = 1
for key in pairs(dictionary) do
new[index] = key
index = index + 1
end
return new
end
return keys
@@ -0,0 +1,74 @@
return function()
local keys = require(script.Parent.keys)
local None = require(script.Parent.Parent.None)
it("should not mutate the given table", function()
local a = {
Foo = "FooValue",
Bar = "BarValue"
}
local aCopy = {
Foo = "FooValue",
Bar = "BarValue"
}
keys(a)
for key, value in pairs(a) do
expect(aCopy[key]).to.equal(value)
end
for key, value in pairs(aCopy) do
expect(a[key]).to.equal(value)
end
end)
it("should return the correct keys", function()
local a = {
Foo = "FooValue",
Bar = "BarValue",
Test = "TestValue"
}
local keyCount = {
Foo = 1,
Bar = 1,
Test = 1
}
local b = keys(a)
expect(#b).to.equal(3)
for _, key in ipairs(b) do
expect(keyCount[key]).never.to.equal(nil)
keyCount[key] = keyCount[key] - 1
end
for _, count in pairs(keyCount) do
expect(count).to.equal(0)
end
end)
it("should work with an empty table", function()
local a = keys({})
expect(next(a)).to.equal(nil)
end)
it("should contain a None element if there is a None key in the dictionary", function()
local a = {
[None] = "Foo",
Bar = "BarValue"
}
local keyCount = {
[None] = 1,
Bar = 1
}
local b = keys(a)
expect(#b).to.equal(2)
for _, key in ipairs(b) do
expect(keyCount[key]).never.to.equal(nil)
keyCount[key] = keyCount[key] - 1
end
for _, count in pairs(keyCount) do
expect(count).to.equal(0)
end
end)
end
@@ -0,0 +1,17 @@
--[[
Returns a list of the values of the given dictionary.
]]
local function values(dictionary)
local new = {}
local index = 1
for _, value in pairs(dictionary) do
new[index] = value
index = index + 1
end
return new
end
return values
@@ -0,0 +1,96 @@
return function()
local values = require(script.Parent.values)
local None = require(script.Parent.Parent.None)
it("should not mutate the given table", function()
local a = {
Foo = "FooValue",
Bar = "BarValue"
}
local aCopy = {
Foo = "FooValue",
Bar = "BarValue"
}
values(a)
for key, value in pairs(a) do
expect(aCopy[key]).to.equal(value)
end
for key, value in pairs(aCopy) do
expect(a[key]).to.equal(value)
end
end)
it("should return the correct values", function()
local a = {
Foo = "FooValue",
Bar = "BarValue",
Test = "TestValue"
}
local valueCount = {
FooValue = 1,
BarValue = 1,
TestValue = 1
}
local b = values(a)
expect(#b).to.equal(3)
for _, value in ipairs(b) do
expect(valueCount[value]).never.to.equal(nil)
valueCount[value] = valueCount[value] - 1
end
for _, count in pairs(valueCount) do
expect(count).to.equal(0)
end
end)
it("should return duplicates if two values are the same", function()
local a = {
Foo = "FooValue",
Bar = "BarValue",
Test = "FooValue"
}
local valueCount = {
FooValue = 2,
BarValue = 1,
}
local b = values(a)
expect(#b).to.equal(3)
for _, value in ipairs(b) do
expect(valueCount[value]).never.to.equal(nil)
valueCount[value] = valueCount[value] - 1
end
for _, count in pairs(valueCount) do
expect(count).to.equal(0)
end
end)
it("should work with an empty table", function()
local a = values({})
expect(next(a)).to.equal(nil)
end)
it("should contain a None element if there is a None value in the dictionary", function()
local a = {
Foo = None,
Bar = "BarValue"
}
local valueCount = {
[None] = 1,
BarValue = 1
}
local b = values(a)
expect(#b).to.equal(2)
for _, value in ipairs(b) do
expect(valueCount[value]).never.to.equal(nil)
valueCount[value] = valueCount[value] - 1
end
for _, count in pairs(valueCount) do
expect(count).to.equal(0)
end
end)
end
@@ -0,0 +1,20 @@
--[[
Create a copy of a list with only values for which `callback` returns true.
Calls the callback with (value, index).
]]
local function filter(list, callback)
local new = {}
local index = 1
for i = 1, #list do
local value = list[i]
if callback(value, i) then
new[index] = value
index = index + 1
end
end
return new
end
return filter
@@ -0,0 +1,77 @@
return function()
local filter = require(script.Parent.filter)
it("should call the callback for each element", function()
local a = {
"foo1",
"foo2",
"foo3"
}
local copy = {}
local function copyCallback(value, index)
copy[index] = value
return true
end
filter(a, copyCallback)
for key, value in pairs(a) do
expect(copy[key]).to.equal(value)
end
for key, value in pairs(copy) do
expect(value).to.equal(a[key])
end
end)
it("should correctly use the filter callback", function()
local a = {1, 2, 3, 4, 5}
local function evenOnly(value)
return value % 2 == 0
end
local b = filter(a, evenOnly)
expect(#b).to.equal(2)
expect(b[1]).to.equal(2)
expect(b[2]).to.equal(4)
end)
it("should copy the list correctly", function()
local a = {1, 2, 3}
local function keepAll()
return true
end
local b = filter(a, keepAll)
expect(b).never.to.equal(a)
for key, value in pairs(a) do
expect(b[key]).to.equal(value)
end
for key, value in pairs(b) do
expect(value).to.equal(a[key])
end
end)
it("should work with an empty table", function()
local called = false
local function callback()
called = true
return true
end
local a = filter({}, callback)
expect(#a).to.equal(0)
expect(called).to.equal(false)
end)
it("should remove all element from a list when callback return always false", function()
local a = {6, 2, 8, 6, 7}
local function removeAll()
return false
end
local b = filter(a, removeAll)
expect(#b).to.equal(0)
end)
end
@@ -0,0 +1,23 @@
--[[
Create a copy of a list doing a combination filter and map.
If callback returns nil for any item, it is considered filtered from the
list. Any other value is considered the result of the 'map' operation.
]]
local function filterMap(list, callback)
local new = {}
local index = 1
for i = 1, #list do
local result = callback(list[i], i)
if result ~= nil then
new[index] = result
index = index + 1
end
end
return new
end
return filterMap
@@ -0,0 +1,92 @@
return function()
local filterMap = require(script.Parent.filterMap)
it("should return a new table", function()
local a = {1, 2, 3}
local function callback()
return 1
end
local b = filterMap(a, callback)
expect(b).never.to.equal(a)
end)
it("should call the callback for each element", function()
local a = {
"foo1",
"foo2",
"foo3"
}
local copy = {}
local function callback(value, index)
copy[index] = value
return value
end
filterMap(a, callback)
for key, value in pairs(a) do
expect(copy[key]).to.equal(value)
end
for key, value in pairs(copy) do
expect(value).to.equal(a[key])
end
end)
it("should correctly use the filter callback", function()
local a = {1, 2, 3, 4, 5}
local function doubleOddOnly(value)
if value % 2 == 0 then
return nil
else
return value * 2
end
end
local b = filterMap(a, doubleOddOnly)
expect(#b).to.equal(3)
expect(b[1]).to.equal(2)
expect(b[2]).to.equal(6)
expect(b[3]).to.equal(10)
end)
it("should copy the list correctly", function()
local a = {1, 2, 3}
local function copyCallback(value)
return value
end
local b = filterMap(a, copyCallback)
expect(b).never.to.equal(a)
for key, value in pairs(a) do
expect(b[key]).to.equal(value)
end
for key, value in pairs(b) do
expect(value).to.equal(a[key])
end
end)
it("should work with an empty table", function()
local called = false
local function callback()
called = true
return true
end
local a = filterMap({}, callback)
expect(#a).to.equal(0)
expect(called).to.equal(false)
end)
it("should remove all elements from a list when callback return always nil", function()
local a = {6, 2, 8, 6, 7}
local function removeAll()
return nil
end
local b = filterMap(a, removeAll)
expect(#b).to.equal(0)
end)
end
@@ -0,0 +1,14 @@
--[[
Returns the index of the first value found or nil if not found.
]]
local function find(list, value)
for i = 1, #list do
if list[i] == value then
return i
end
end
return nil
end
return find
@@ -0,0 +1,30 @@
return function()
local find = require(script.Parent.find)
it("should return the correct index", function()
local a = {5, 4, 3, 2, 1}
expect(find(a, 1)).to.equal(5)
expect(find(a, 2)).to.equal(4)
expect(find(a, 3)).to.equal(3)
expect(find(a, 4)).to.equal(2)
expect(find(a, 5)).to.equal(1)
end)
it("should work with an empty table", function()
expect(find({}, 1)).to.equal(nil)
end)
it("should return nil when the given value is not found", function()
local a = {1, 2, 3}
expect(find(a, 4)).to.equal(nil)
expect(type(find(a, 4))).to.equal("nil")
end)
it("should return the index of the first value found", function()
local list = {1, 2, 2}
expect(find(list, 2)).to.equal(2)
end)
end
@@ -0,0 +1,14 @@
--[[
Returns the index of the first value for which predicate(value, index) is truthy, or nil if not found.
]]
local function findWhere(list, predicate)
for i = 1, #list do
if predicate(list[i], i) then
return i
end
end
return nil
end
return findWhere
@@ -0,0 +1,63 @@
return function()
local findWhere = require(script.Parent.findWhere)
it("should return the correct index", function()
local numbers = { 1, 5, 10, 7 }
local isEven = function(value)
return value % 2 == 0
end
local isOdd = function(value)
return value % 2 == 1
end
expect(findWhere(numbers, isEven)).to.equal(3)
expect(findWhere(numbers, isOdd)).to.equal(1)
end)
it("should work with an empty table", function()
local anything = function()
return true
end
expect(findWhere({}, anything)).to.equal(nil)
end)
it("should return nil when the when no value satisfies the predicate", function()
local numbers = { 1, 2, 3 }
local isFour = function(value)
return value == 4
end
expect(findWhere(numbers, isFour)).to.equal(nil)
end)
it("should return the index of the first value for which the predicate is true", function()
local list = { 1, 1, 1, 2, 2 }
local isTwo = function(value)
return value == 2
end
expect(findWhere(list, isTwo)).to.equal(4)
end)
it("should allow access to table index in the predicate function", function()
local list = { 5, 4, 3, 2, 1 }
local isIndexFour = function(_, index)
return index == 4
end
expect(findWhere(list, isIndexFour)).to.equal(4)
end)
it("should allow access to both value and index in the predicate function", function()
local list = { 1, 1, 2, 2, 1 }
local sumValueAndIndexToFive = function(value, index)
return value + index == 5
end
expect(findWhere(list, sumValueAndIndexToFive)).to.equal(3)
end)
end
@@ -0,0 +1,14 @@
--[[
Performs a left-fold of the list with the given initial value and callback.
]]
local function foldLeft(list, callback, initialValue)
local accum = initialValue
for i = 1, #list do
accum = callback(accum, list[i], i)
end
return accum
end
return foldLeft
@@ -0,0 +1,61 @@
return function()
local foldLeft = require(script.Parent.foldLeft)
it("should call the callback", function()
local a = {1, 2, 3}
local called = 0
foldLeft(a, function()
called = called + 1
end, 0)
expect(called).to.equal(3)
end)
it("should not call the callback when the list is empty", function()
local called = false
foldLeft({}, function()
called = true
end, 0)
expect(called).to.equal(false)
end)
it("should call the callback for each element", function()
local a = {4, 5, 6}
local copy = {}
foldLeft(a, function(accum, value, index)
copy[index] = value
return accum
end, 0)
expect(#copy).to.equal(#a)
for key, value in pairs(a) do
expect(value).to.equal(copy[key])
end
end)
it("should pass the same modified initial value to the callback", function()
local a = {5, 4, 3}
local initialValue = {}
foldLeft(a, function(accum)
expect(accum).to.equal(initialValue)
return accum
end, initialValue)
end)
it("should call the callback in the correct order", function()
local a = {5, 4, 3}
local index = 1
foldLeft(a, function(accum, value)
expect(value).to.equal(a[index])
index = index + 1
return accum
end, 0)
end)
end
@@ -0,0 +1,14 @@
--[[
Performs a right-fold of the list with the given initial value and callback.
]]
local function foldRight(list, callback, initialValue)
local accum = initialValue
for i = #list, 1, -1 do
accum = callback(accum, list[i], i)
end
return accum
end
return foldRight
@@ -0,0 +1,61 @@
return function()
local foldRight = require(script.Parent.foldRight)
it("should call the callback", function()
local a = {1, 2, 3}
local called = 0
foldRight(a, function()
called = called + 1
end, 0)
expect(called).to.equal(3)
end)
it("should not call the callback when the list is empty", function()
local called = false
foldRight({}, function()
called = true
end, 0)
expect(called).to.equal(false)
end)
it("should call the callback for each element", function()
local a = {4, 5, 6}
local copy = {}
foldRight(a, function(accum, value, index)
copy[index] = value
return accum
end, 0)
expect(#copy).to.equal(#a)
for key, value in pairs(a) do
expect(value).to.equal(copy[key])
end
end)
it("should pass the same modified initial value to the callback", function()
local a = {5, 4, 3}
local initialValue = {}
foldRight(a, function(accum)
expect(accum).to.equal(initialValue)
return accum
end, initialValue)
end)
it("should call the callback in the correct order", function()
local a = {5, 4, 3}
local index = 3
foldRight(a, function(accum, value)
expect(value).to.equal(a[index])
index = index - 1
return accum
end, 0)
end)
end
@@ -0,0 +1,19 @@
--[[
Returns a new list containing only the elements within the given range.
]]
local function getRange(list, startIndex, endIndex)
assert(startIndex <= endIndex, "startIndex must be less than or equal to endIndex")
local new = {}
local index = 1
for i = math.max(1, startIndex), math.min(#list, endIndex) do
new[index] = list[i]
index = index + 1
end
return new
end
return getRange
@@ -0,0 +1,62 @@
return function()
local getRange = require(script.Parent.getRange)
it("should return the correct range", function()
local a = {1, 2, 3, 4}
local b = getRange(a, 2, 3)
expect(b[1]).to.equal(2)
expect(b[2]).to.equal(3)
expect(#b).to.equal(2)
local c = getRange(a, 4, 4)
expect(#c).to.equal(1)
expect(c[1]).to.equal(4)
end)
it("should throw when the start index is higher than the end index", function()
local a = {5, 8, 7, 2, 3, 7}
expect(function()
getRange(a, 4, 1)
end).to.throw()
end)
it("should copy the table", function()
local a = {6, 8, 1, 3, 7, 2}
local b = getRange(a, 1, #a)
for key, value in pairs(a) do
expect(b[key]).to.equal(value)
end
for key, value in pairs(b) do
expect(value).to.equal(a[key])
end
end)
it("should work with an empty table", function()
local a = getRange({}, 1, 5)
expect(a).to.be.a("table")
expect(#a).to.equal(0)
end)
it("should work when the start index is smaller that 1", function()
local a = {1, 2, 3, 4}
local b = getRange(a, -2, 2)
expect(#b).to.equal(2)
expect(b[1]).to.equal(1)
expect(b[2]).to.equal(2)
end)
it("should work when the end index is larger that the list length", function()
local a = {1, 2, 3, 4}
local b = getRange(a, 3, 18)
expect(#b).to.equal(2)
expect(b[1]).to.equal(3)
expect(b[2]).to.equal(4)
end)
end
@@ -0,0 +1,22 @@
--[[
Defines utilities for working with 'list-like' tables.
]]
return {
filter = require(script.filter),
filterMap = require(script.filterMap),
find = require(script.find),
findWhere = require(script.findWhere),
foldLeft = require(script.foldLeft),
foldRight = require(script.foldRight),
getRange = require(script.getRange),
join = require(script.join),
map = require(script.map),
removeIndex = require(script.removeIndex),
removeRange = require(script.removeRange),
removeValue = require(script.removeValue),
replaceIndex = require(script.replaceIndex),
reverse = require(script.reverse),
sort = require(script.sort),
toSet = require(script.toSet),
}
@@ -0,0 +1,5 @@
return function()
it("should load", function()
require(script.Parent)
end)
end
@@ -0,0 +1,25 @@
local None = require(script.Parent.Parent.None)
--[[
Joins any number of lists together into a new list
]]
local function join(...)
local new = {}
for listKey = 1, select("#", ...) do
local list = select(listKey, ...)
local len = #new
for itemKey = 1, #list do
if list[itemKey] == None then
len = len - 1
else
new[len + itemKey] = list[itemKey]
end
end
end
return new
end
return join
@@ -0,0 +1,44 @@
return function()
local join = require(script.Parent.join)
local None = require(script.Parent.Parent.None)
it("should return a new table", function()
local a = {}
expect(join(a)).never.to.equal(a)
end)
it("should remove elements equal to None", function()
local a = {
"foo-a"
}
local b = {
None,
"foo-b"
}
local c = join(a, b)
expect(c[1]).to.equal("foo-a")
expect(c[2]).to.equal("foo-b")
expect(c[3]).to.equal(nil)
end)
it("should accept arbitrary numbers of tables", function()
local a = {1}
local b = {2}
local c = {3}
local d = join(a, b, c)
expect(#d).to.equal(3)
expect(d[1]).to.equal(1)
expect(d[2]).to.equal(2)
expect(d[3]).to.equal(3)
end)
it("should accept zero tables", function()
expect(join()).to.be.a("table")
end)
end
@@ -0,0 +1,14 @@
--[[
Create a copy of a list where each value is transformed by `callback`
]]
local function map(list, callback)
local new = {}
for i = 1, #list do
new[i] = callback(list[i], i)
end
return new
end
return map
@@ -0,0 +1,61 @@
return function()
local map = require(script.Parent.map)
it("should return a new table", function()
local a = {1, 2, 3}
expect(map(a, function() end)).never.to.equal(a)
end)
it("should call the callback for each element", function()
local a = {5, 6, 7}
local copy = {}
map(a, function(value, index)
copy[index] = value
return value
end)
for key, value in pairs(a) do
expect(copy[key]).to.equal(value)
end
for key, value in pairs(copy) do
expect(value).to.equal(a[key])
end
end)
it("should copy list", function()
local a = {1, 2, 3}
local b = map(a, function(value)
return value
end)
for key, value in pairs(a) do
expect(b[key]).to.equal(value)
end
for key, value in pairs(b) do
expect(value).to.equal(a[key])
end
end)
it("should sets the new values to the result of the given callback", function()
local a = {5, 6, 7}
local b = map(a, function(value)
return value * 2
end)
expect(#b).to.equal(#a)
for i = 1, #a do
expect(b[i]).to.equal(a[i] * 2)
end
end)
it("should work with an empty list", function()
local a = {}
local b = map(a, function() end)
expect(b).to.be.a("table")
expect(b).never.to.equal(a)
end)
end
@@ -0,0 +1,19 @@
--[[
Remove the element at the given index.
]]
local function removeIndex(list, index)
local new = {}
local removed = 0
for i = 1, #list do
if i == index then
removed = 1
else
new[i - removed] = list[i]
end
end
return new
end
return removeIndex
@@ -0,0 +1,53 @@
return function()
local removeIndex = require(script.Parent.removeIndex)
local None = require(script.Parent.Parent.None)
it("should remove the element at the given index", function()
local a = {
"first",
"second",
"third"
}
local b = removeIndex(a, 2)
expect(#b).to.equal(2)
expect(b[1]).to.equal("first")
expect(b[2]).to.equal("third")
end)
it("should not remove any element if index is out of bound", function()
local a = {
"first",
"second",
"third"
}
local b = removeIndex(a, 4)
expect(#b).to.equal(#a)
for i = 1, #a do
expect(b[i]).to.equal(a[i])
end
local c = removeIndex(a, -2)
expect(#c).to.equal(#a)
for i = 1, #a do
expect(c[i]).to.equal(a[i])
end
end)
it("should work with a None element", function()
local a = {
"first",
None,
"third"
}
local b = removeIndex(a, 1)
expect(#b).to.equal(2)
expect(b[1]).to.equal(None)
expect(b[2]).to.equal("third")
end)
end
@@ -0,0 +1,23 @@
--[[
Remove the range from the list starting from the index.
]]
local function removeRange(list, startIndex, endIndex)
assert(startIndex <= endIndex, "startIndex must be less than or equal to endIndex")
local new = {}
local index = 1
for i = 1, math.min(#list, startIndex - 1) do
new[index] = list[i]
index = index + 1
end
for i = endIndex + 1, #list do
new[index] = list[i]
index = index + 1
end
return new
end
return removeRange
@@ -0,0 +1,75 @@
return function()
local removeRange = require(script.Parent.removeRange)
local None = require(script.Parent.Parent.None)
it("should remove elements properly", function()
local a = {1, 2, 3}
local b = removeRange(a, 2, 2)
expect(#b).to.equal(2)
expect(b[1]).to.equal(1)
expect(b[2]).to.equal(3)
local c = {1, 2, 3, 4, 5, 6}
local d = removeRange(c, 1, 4)
expect(#d).to.equal(2)
expect(d[1]).to.equal(5)
expect(d[2]).to.equal(6)
local e = removeRange(c, 2, 5)
expect(#e).to.equal(2)
expect(e[1]).to.equal(1)
expect(e[2]).to.equal(6)
end)
it("should throw when the start index is higher than the end index", function()
local a = {1, 2, 3}
expect(function()
removeRange(a, 2, 0)
end).to.throw()
expect(function()
removeRange(a, 1, -1)
end).to.throw()
end)
it("should copy the table when then indexes are higher than the list length", function()
local a = {1, 2, 3}
local b = removeRange(a, 4, 7)
expect(#b).to.equal(3)
expect(b[1]).to.equal(1)
expect(b[2]).to.equal(2)
expect(b[3]).to.equal(3)
end)
it("should work when the start index is smaller than 1", function()
local a = {1, 2, 3, 4}
local b = removeRange(a, -5, 2)
expect(#b).to.equal(2)
expect(b[1]).to.equal(3)
expect(b[2]).to.equal(4)
end)
it("should work when the end index is greater than the list length", function()
local a = {1, 2, 3, 4}
local b = removeRange(a, 3, 8)
expect(#b).to.equal(2)
expect(b[1]).to.equal(1)
expect(b[2]).to.equal(2)
end)
it("should work with a None element", function()
local a = {1, None, 3}
local b = removeRange(a, 1, 1)
expect(#b).to.equal(2)
expect(b[1]).to.equal(None)
expect(b[2]).to.equal(3)
end)
end
@@ -0,0 +1,18 @@
--[[
Creates a new list that has no occurrences of the given value.
]]
local function removeValue(list, value)
local new = {}
local index = 1
for i = 1, #list do
if list[i] ~= value then
new[index] = list[i]
index = index + 1
end
end
return new
end
return removeValue
@@ -0,0 +1,43 @@
return function()
local removeValue = require(script.Parent.removeValue)
local None = require(script.Parent.Parent.None)
it("should remove the given value", function()
local a = {1, 4, 3}
local b = removeValue(a, 4)
expect(b[1]).to.equal(1)
expect(b[2]).to.equal(3)
end)
it("should remove all occurences of the same given value", function()
local a = {1, 2, 2, 3}
local b = removeValue(a, 2)
expect(#b).to.equal(2)
expect(b[1]).to.equal(1)
expect(b[2]).to.equal(3)
end)
it("should work with an empty list", function()
local a = removeValue({}, 1)
expect(a).to.be.a("table")
expect(#a).to.equal(0)
end)
it("should work with a None element", function()
local a = {1, 2, None, 3}
local b = removeValue(a, 2)
expect(#b).to.equal(3)
expect(b[1]).to.equal(1)
expect(b[2]).to.equal(None)
expect(b[3]).to.equal(3)
local c = removeValue(a, None)
expect(c[3]).to.equal(3)
expect(#c).to.equal(3)
end)
end
@@ -0,0 +1,22 @@
--[[
Returns a new list with the new value replaced at the given index.
]]
local function replaceIndex(list, index, value)
local new = {}
local len = #list
assert(index <= len, "index must be less or equal than the list length")
for i = 1, len do
if i == index then
new[i] = value
else
new[i] = list[i]
end
end
return new
end
return replaceIndex
@@ -0,0 +1,52 @@
return function()
local replaceIndex = require(script.Parent.replaceIndex)
it("should return a new table", function()
local list = {1, 2, 3}
expect(replaceIndex(list, 2, 0)).never.to.equal(list)
end)
it("should not mutate the original list", function()
local list = {false, "foo", 3}
local value = {}
replaceIndex(list, 2, value)
expect(#list).to.equal(3)
expect(list[1]).to.equal(false)
expect(list[2]).to.equal("foo")
expect(list[3]).to.equal(3)
end)
it("should replace the value at the given index", function()
local list = {1, 2, 3}
local value = {}
local result = replaceIndex(list, 2, value)
expect(result[1]).to.equal(1)
expect(result[2]).to.equal(value)
expect(result[3]).to.equal(3)
expect(next(result[2])).to.equal(nil)
end)
it("should throw if the given index is higher than the list length", function()
local list = {1}
expect(function()
replaceIndex(list, #list + 1, {})
end).to.throw()
end)
it("should be able to replace to a falsy value", function()
local tableElement = {}
local list = {tableElement, false, "value", true}
local newValue = false
local result = replaceIndex(list, 3, newValue)
expect(result[1]).to.equal(tableElement)
expect(result[2]).to.equal(false)
expect(result[3]).to.equal(newValue)
expect(result[4]).to.equal(true)
end)
end
@@ -0,0 +1,17 @@
--[[
Returns a new list with the reversed order of the given list
]]
local function reverse(list)
local new = {}
local len = #list
local top = len + 1
for i = 1, len do
new[i] = list[top - i]
end
return new
end
return reverse
@@ -0,0 +1,46 @@
return function()
local reverse = require(script.Parent.reverse)
it("should return a new table", function()
local a = {1, 2, 3}
expect(reverse(a)).never.to.equal(a)
end)
it("should not mutate the given table", function()
local a = {1, 2, 3}
reverse(a)
expect(#a).to.equal(3)
expect(a[1]).to.equal(1)
expect(a[2]).to.equal(2)
expect(a[3]).to.equal(3)
end)
it("should contain the same elements", function()
local a = {
"Foo",
"Bar"
}
local aSet = {
Foo = true,
Bar = true
}
local b = reverse(a)
expect(#b).to.equal(2)
for _, value in ipairs(b) do
expect(aSet[value]).to.equal(true)
end
end)
it("should reverse the list", function()
local a = {1, 2, 3, 4}
local b = reverse(a)
expect(b[1]).to.equal(4)
expect(b[2]).to.equal(3)
expect(b[3]).to.equal(2)
expect(b[4]).to.equal(1)
end)
end
@@ -0,0 +1,18 @@
--[[
Returns a new list, ordered with the given sort callback.
If no callback is given, the default table.sort will be used.
]]
local function sort(list, callback)
local new = {}
for i = 1, #list do
new[i] = list[i]
end
table.sort(new, callback)
return new
end
return sort
@@ -0,0 +1,74 @@
return function()
local sort = require(script.Parent.sort)
it("should return a new table", function()
local a = {}
expect(sort(a)).never.to.equal(a)
end)
it("should not mutate the given table", function()
local a = {77, "foo", 2}
local function order(first, second)
return tostring(first) < tostring(second)
end
sort(a, order)
expect(#a).to.equal(3)
expect(a[1]).to.equal(77)
expect(a[2]).to.equal("foo")
expect(a[3]).to.equal(2)
end)
it("should contain the same elements from the given table", function()
local a = {
"Foo",
"Bar",
"Test"
}
local elementSet = {
Foo = true,
Bar = true,
Test = true
}
local b = sort(a)
expect(#b).to.equal(3)
for _, value in ipairs(b) do
expect(elementSet[value]).to.equal(true)
end
end)
it("should sort with the default table.sort when no callback is given", function()
local a = {4, 2, 5, 3, 1}
local b = sort(a)
table.sort(a)
expect(#b).to.equal(#a)
for i = 1, #a do
expect(b[i]).to.equal(a[i])
end
end)
it("should sort with the given callback", function()
local a = {1, 2, 5, 3, 4}
local function order(first, second)
return first > second
end
local b = sort(a, order)
table.sort(a, order)
expect(#b).to.equal(#a)
for i = 1, #a do
expect(b[i]).to.equal(a[i])
end
end)
it("should work with an empty table", function()
local a = sort({})
expect(#a).to.equal(0)
end)
end
@@ -0,0 +1,16 @@
--[[
Create a dictionary where each value in the given list corresponds to a key
in the dictionary with a value of true
]]
local function toSet(list)
local new = {}
for i = 1, #list do
new[list[i]] = true
end
return new
end
return toSet
@@ -0,0 +1,42 @@
return function()
local toSet = require(script.Parent.toSet)
it("should return a new table", function()
local a = {1, 2, 3}
expect(toSet(a)).never.to.equal(a)
end)
it("should not mutate the given table", function()
local a = {"a", "b", "c"}
toSet(a)
for k, v in pairs(a) do
if k == 1 then
expect(v).to.equal("a")
elseif k == 2 then
expect(v).to.equal("b")
elseif k == 3 then
expect(v).to.equal("c")
else
error("Extra key was added to table a")
end
end
end)
it("should have every value in a as a key mapped to true in b", function()
local a = {1, 2, 3, "a", "b", "c"}
local b = toSet(a)
expect(#b).to.equal(3)
expect(b[1]).to.equal(true)
expect(b[2]).to.equal(true)
expect(b[3]).to.equal(true)
expect(b[4]).to.equal(nil)
expect(b["a"]).to.equal(true)
expect(b["b"]).to.equal(true)
expect(b["c"]).to.equal(true)
end)
end
@@ -0,0 +1,15 @@
--[[
Represents a value that is intentionally present, but should be interpreted
as `nil`.
Cryo.None is used by included utilities to make removing values more
ergonomic.
]]
local None = newproxy(true)
getmetatable(None).__tostring = function()
return "Cryo.None"
end
return None
@@ -0,0 +1,14 @@
return function()
local None = require(script.Parent.None)
it("should be a userdata", function()
expect(None).to.be.a("userdata")
end)
it("should have a nice string name", function()
local coerced = tostring(None)
expect(coerced:find("^userdata: ")).never.to.be.ok()
expect(coerced:find("None")).to.be.ok()
end)
end
@@ -0,0 +1,6 @@
return {
Dictionary = require(script.Dictionary),
List = require(script.List),
isEmpty = require(script.isEmpty),
None = require(script.None),
}
@@ -0,0 +1,5 @@
return function()
it("should load", function()
require(script.Parent)
end)
end
@@ -0,0 +1,5 @@
local function isEmpty(object)
return next(object) == nil
end
return isEmpty
@@ -0,0 +1,5 @@
# Generated by Rotriever. Format subject to change in future releases.
name = "roblox/cryo"
version = "1.0.0"
commit = "272caa8f3f3b3b29296b462f80b65cc9b1c92f1e"
source = "url+https://github.com/roblox/cryo"