diff --git a/.gitignore b/.gitignore index f0deb4d..77b402b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .env .env.* *.tsbuildinfo +sourcemap.json /Packages /DevPackages diff --git a/.luaurc b/.luaurc index cfbdb52..06b85fb 100644 --- a/.luaurc +++ b/.luaurc @@ -3,6 +3,7 @@ "lint": { "*": false }, "aliases": { "Pkg": "Packages", - "DevPkg": "DevPackages" + "DevPkg": "DevPackages", + "Sift": "src" } } diff --git a/.vscode/settings.json b/.vscode/settings.json index 1acaf69..5a1a07f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,6 +14,10 @@ }, "luau-lsp.require.directoryAliases": { "@Pkg": "Packages", - "@DevPkg": "DevPackages" - } + "@DevPkg": "DevPackages", + "@Sift": "src" + }, + "luau-lsp.types.roblox": false, + "luau-lsp.require.mode": "relativeToFile", + "luau-lsp.completion.imports.suggestRequires": false } diff --git a/@types/Array.d.ts b/@types/Array.d.ts deleted file mode 100644 index 6ef8f70..0000000 --- a/@types/Array.d.ts +++ /dev/null @@ -1,187 +0,0 @@ -import type { ReadonlyDeep, ReplaceType, SiftNone } from "./Util" - -declare namespace SiftArray { - export function at( - array: V[], - index: number - ): V | undefined - - export function concat(...arrays: T[]): T - - export function concatDeep(...arrays: T[]): T - - export function copy(array: T): T - - export function copyDeep(array: T): T - - export function count( - array: T[], - predicate: (value: T, index: number, array: Readonly) => unknown - ): number - - export function create(length: number, value?: T): T[] - - export function difference(array: T[], ...values: T[]): T[] - - export function differenceSymmetric(array: T[], ...values: T[]): T[] - - export function equals(...arrays: unknown[]): boolean - - export function equalsDeep(...arrays: unknown[]): boolean - - export function every( - array: T[], - predicate: (value: T, index: number, array: Readonly) => unknown - ): boolean - - export function filter( - array: T[], - filterer?: (value: T, index: number, array: Readonly) => unknown - ): T[] - - export function find( - array: T[], - value?: T, - from?: number - ): number | undefined - - export function findLast( - array: T[], - value?: T, - from?: number - ): number | undefined - - export function findWhere( - array: T[], - predicate: (value: T, index: number, array: Readonly) => unknown, - from?: number - ): number - - export function findWhereLast( - array: T[], - predicate: (value: T, index: number, array: Readonly) => unknown, - from?: number - ): number - - export function first(array: T[]): T - - export function flatten(array: T[], depth?: number): T[] - - export function freeze(array: T[]): Readonly - - export function freezeDeep(array: T[]): ReadonlyDeep - - export function includes(array: T[], value: T, from?: number): boolean - - export function insert(array: T[], index: number, ...values: T[]): T[] - - export function is(value: any): boolean - - export function last(array: T[]): T - - export function map( - array: T[], - mapper: (value: T, index: number, array: Readonly) => U - ): U[] - - export function pop(array: T[], count?: number): T[] - - export function push(array: T[], ...values: T[]): T[] - - export function reduce( - array: T[], - reducer: ( - accumulator: U, - value: T, - index: number, - array: Readonly - ) => U, - initialValue?: U - ): U - - export function reduceRight( - array: T[], - reducer: ( - accumulator: U, - value: T, - index: number, - array: Readonly - ) => U, - initialValue?: U - ): U - - export function removeIndex(array: T[], index: number): T[] - - export function removeIndices(array: T[], ...indices: number[]): T[] - - export function removeValue(array: T[], value: T): T[] - - export function removeValues(array: T[], ...values: T[]): T[] - - export function reverse(array: T[]): T[] - - export function set(array: T[], index: number, value: T): T[] - - export function shift(array: T[], count?: number): T[] - - export function shuffle(array: T[]): T[] - - export function slice(array: T[], from?: number, to?: number): T[] - - export function some( - array: T[], - predicate: (value: T, index: number, array: Readonly) => unknown - ): boolean - - export function sort(array: T[], comparator?: (a: T, b: T) => unknown): T[] - - export function splice( - array: T[], - start?: number, - end?: number, - ...values: T[] - ): T[] - - export function toSet(array: T[]): Set - - export function unshift(array: T[], ...values: T[]): T[] - - export function update( - array: T[], - index: number, - updater?: (value: T, index: number) => T, - callback?: (index: number) => T - ): T[] - - export function zip( - ...arrays: T - ): { - [K in keyof T]: T[K] extends (infer V)[] ? V : never - }[] - - export function zipAll( - ...arrays: T - ): { - [K in keyof T]: ReplaceType< - T[K] extends (infer V)[] ? V : never, - undefined, - SiftNone - > - }[] - - // Aliases - export { - concat as join, - concat as merge, - concatDeep as joinDeep, - concatDeep as mergeDeep, - find as indexOf, - includes as contains, - includes as has, - push as append, - unshift as prepend, - is as isArray, - } -} - -export = SiftArray diff --git a/@types/Dictionary.d.ts b/@types/Dictionary.d.ts deleted file mode 100644 index dd71e15..0000000 --- a/@types/Dictionary.d.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { - ExcludeNone, - FromEntries, - ObjectFromKeyValueArrays, - ObjectKey, - ReadonlyDeep, - TryIndex -} from "./Util" - -declare namespace SiftDictionary { - export function copy(dictionary: T): T - - export function copyDeep(dictionary: T): T - - export function count( - dictionary: T, - predicate?: (value: T[K], key: K, dictionary: T) => unknown - ): number - - export function entries( - dictionary: T - ): [K, T[K]][] - - export function equals(...dictionaries: object[]): boolean - - export function equalsDeep(...dictionaries: object[]): boolean - - export function every( - dictionary: T, - predicate: (value: T[K], key: K, dictionary: Readonly) => unknown - ): boolean - - export function filter( - dictionary: T, - predicate: (value: T[K], key: K, dictionary: Readonly) => unknown - ): Partial - - export function flatten( - dictionary: T, - depth?: number - ): Record - - export function flip( - dictionary: T - ): Record - - export function freeze(dictionary: T): Readonly - - export function freezeDeep(dictionary: T): ReadonlyDeep - - export function fromArrays( - keys: K[], - values: V[] - ): ObjectFromKeyValueArrays - - export function fromEntries( - entries: T - ): FromEntries - - export function has(dictionary: T, key: unknown): boolean - - export function includes( - dictionary: T, - value: unknown - ): boolean - - export function keys(dictionary: T): K[] - - export function map< - T extends object, - MV, - MK extends ObjectKey, - K extends keyof T - >( - dictionary: T, - mapper: ( - value: T[K], - key: K, - dictionary: Readonly - ) => LuaTuple<[newValue: MV, newKey: MK]> | undefined - ): { - [key in MK]: MV - } - - export function map( - dictionary: T, - mapper: (value: T[K], key: K, dictionary: Readonly) => MV | undefined - ): { - [key in K]: MV - } - - export function merge( - ...dictionaries: T - ): ExcludeNone> - - export function mergeDeep( - ...dictionaries: T - ): ExcludeNone> - - export function removeKey( - dictionary: T, - key: K - ): Omit - - export function removeKeys( - dictionary: T, - ...keys: K[] - ): Omit - - export function removeValue( - dictionary: T, - value: V - ): ExcludeMembers - - export function removeValues( - dictionary: T, - ...values: V - ): ExcludeMembers - - export function set( - dictionary: T, - key: K, - value: V - ): T & { [key in K]: V } - - export function set( - dictionary: T, - key: K, - value: V - ): T & { [key in K]: V } - - export function some( - dictionary: T, - predicate: (value: T[K], key: K, dictionary: Readonly) => unknown - ): boolean - - export function update< - T extends object, - K extends ObjectKey, - X = TryIndex, - Y = undefined - >( - dictionary: T, - key: K, - updater?: (value: TryIndex, key: K) => X, - callback?: (key: K) => Y - ): (TryIndex extends undefined - ? { - [key in keyof T]: key extends K ? X : T[key] - } - : { - [key in keyof T]: key extends K ? Y : T[key] - }) & { [key in K]: X } - - export function values(dictionary: T): T[keyof T][] - - export function withKeys( - dictionary: T, - ...keys: K[] - ): Pick - - // Aliases - export { merge as join, mergeDeep as joinDeep } -} - -export = SiftDictionary diff --git a/@types/Set.d.ts b/@types/Set.d.ts deleted file mode 100644 index 843a702..0000000 --- a/@types/Set.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { AnySet } from "./Util" - -declare namespace SiftSet { - export function add(set: Set, ...values: I[]): Set - - export function copy(set: T): T - - export function count>( - set: S, - predicate?: (item: T) => unknown - ): number - - export function difference(set: Set, ...sets: Set[]): Set - - export function differenceSymmetric(set: Set, ...sets: Set[]): Set - - export function filter>( - set: S, - predicate: (item: T, set: Readonly) => unknown - ): Set - - export function fromArray(array: T[]): Set - - export function has(set: AnySet, item: unknown): boolean - - export function intersection(...sets: Set[]): Set - - export function isSubset( - subset: A, - superset: B - ): boolean - - export function isSuperset( - superset: A, - subset: B - ): boolean - - export function map>( - set: S, - mapper: (item: T, set: Readonly) => R - ): Set - - export function merge(...sets: Set[]): Set - - export function subtract(set: S, ...values: unknown[]): S - - export function toArray(set: Set): T[] - - // Aliases - export { merge as join, merge as union, subtract as delete } -} - -export = SiftSet diff --git a/@types/Util.d.ts b/@types/Util.d.ts deleted file mode 100644 index e2d8c0a..0000000 --- a/@types/Util.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -export type SiftNone = { readonly __none__: unique symbol } -export type ExcludeNone = Exclude -export type ObjectKey = string | number | symbol -export type AnySet = Set - -export type FromEntries = { - [P in T[number][0]]: Extract[1] -} - -export type ReadonlyDeep = T extends (infer U)[] - ? ReadonlyDeepArray - : T extends Callback - ? T - : T extends object - ? ReadonlyDeepObject - : T - -export type ObjectFromKeyValueArrays< - Keys extends Array, - Values extends Array -> = ObjectFromKeyValuePairs> - -export type ReplaceType = F extends T ? Exclude | R : T - -export type TryIndex = K extends keyof T ? T[K] : undefined - -interface ReadonlyDeepArray extends ReadonlyArray> {} - -type ReadonlyDeepObject = { - readonly [P in keyof T]: ReadonlyDeep -} - -type KeyValuePairsFromLists< - Keys extends Array, - Values extends Array -> = { - [index in keyof Keys]: index extends keyof Values - ? [Keys[index], Values[index]] - : never -} - -type ObjectFromKeyValuePairs< - KV extends [ObjectKey, any][], - T = { - [index in keyof KV]: KV[index] extends [ObjectKey, any] - ? Record - : never - } -> = UnionToIntersection diff --git a/@types/index.d.ts b/@types/index.d.ts deleted file mode 100644 index 05946dc..0000000 --- a/@types/index.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { SiftNone } from "./Util" - -import SiftArray from "./Array" -import SiftDictionary from "./Dictionary" -import SiftSet from "./Set" - -declare namespace Sift { - export const None: SiftNone - export type None = SiftNone - - export { - SiftArray as Array, - SiftArray as List, - SiftDictionary as Dictionary, - SiftSet as Set, - } -} - -export = Sift diff --git a/README.md b/README.md index bb2b1a8..90e3175 100644 --- a/README.md +++ b/README.md @@ -100,28 +100,3 @@ As per the recommendations in [Llama's README][freddylist/llama], the following - Organised tests. `*.spec` files are now alongside their source files, making it easier to locate them. - Documentation is now generated using [@upliftgames' moonwave][upliftgames/moonwave] (Docusaurus). This makes it quick and easy to add new documentation, and provides a pleasant experience for the user. - Built-in TypeScript typings. - -## What's New? - -### Arrays (Lists) - -- `at`: Get an element at a specific index (negative indices are supported). -- `difference`: Returns an array of values that are in the first array, but not in the other arrays. -- `differenceSymmetric`: Returns an array of values that are in the first array, but not in the other arrays, and vice versa. -- `freeze`: Freeze an array. -- `freezeDeep`: Freeze an array and all nested arrays. -- `is`: Check if the passed value is an array. -- `shuffle`: Shuffle the elements of an array to a random order. - -### Dictionaries - -- `entries`: Get the entries of a dictionary as an array of key-value pairs. -- `freeze`: Freeze a dictionary. -- `freezeDeep`: Freeze a dictionary and all nested dictionaries. -- `fromEntries`: Create a dictionary from an array of key-value pairs. - -### Sets - -- `count`: Get the number of elements in a set. -- `difference`: Returns a set of values that are in the first set, but not in the other sets. -- `differenceSymmetric`: Returns a set of values that are in the first set, but not in the other sets, and vice versa. diff --git a/docs/Examples.md b/docs/Examples.md deleted file mode 100644 index 2ef92b5..0000000 --- a/docs/Examples.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -sidebar_position: 3 ---- - -Sift contains a number of useful functions for working with data structures. These functions are available as static methods on the Sift module (refer to the [API documentation](/api) for more details). - -```lua -local Sift = require(path.to.Sift) -``` - -Sift also exports Luau types, which can be accessed from the Sift module itself, or via the dedicated Types module, which is exported as `Sift.Types`. - -### Combining Data - -```lua -local dictionary1 = { a = 1, b = 2 } -local dictionary2 = { c = 3, d = 4 } - -local result = Sift.Dictionary.merge(dictionary1, dictionary2) -- { a = 1, b = 2, c = 3, d = 4 } -``` - -```lua -local array1 = { 1, 2, 3 } -local array2 = { 4, 5, 6 } - -local result = Sift.Array.concat(array1, array2) -- { 1, 2, 3, 4, 5, 6 } -``` - -### Filtering Data - -The following example filters out all uneven numbers from an array of numbers. - -```lua -local array = { 1, 2, 3, 4, 5, 6 } - -local result = Sift.Array.filter(array, function(value) - return value % 2 == 0 -end) -- { 2, 4, 6 } -``` - -Dictionaries can also be filtered in Sift! - -```lua -local dictionary = { a = 1, b = 2, c = 3, d = 4 } - -local result = Sift.Dictionary.filter(dictionary, function(value) - return value % 2 == 0 -end) -- { b = 2, d = 4 } -``` - -### Removing Duplicates - -There's a few different methods for removing duplicates from an array or dictionary. - -The following example removes all duplicate values from an array using sets. - -```lua -local array = { "hello", "world", "world", "cat", "dog" } - -local set = Sift.Set.fromArray(array) -- { "hello" = true, "world" = true, "cat" = true, "dog" = true } - -local result = Sift.Set.toArray(set) -- { "hello", "world", "cat", "dog" } -``` - -The same could also be accomplished using a reducer. - -```lua -local array = { "hello", "world", "world", "cat", "dog" } - -local result = Sift.Array.reduce(array, function(accumulator, value) - if not Sift.Array.includes(accumulator, value) then - return Sift.Array.push(accumulator, value) - end - - return accumulator -end, {}) -- { "hello", "world", "cat", "dog" } -``` diff --git a/docs/Installation.md b/docs/Installation.md deleted file mode 100644 index 1756841..0000000 --- a/docs/Installation.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -sidebar_position: 2 ---- - - - -[sift]: https://github.com/cxmeel/sift -[sift/releases]: https://github.com/cxmeel/sift/releases -[sift/wally]: https://wally.run/package/cxmeel/sift -[sift/roblox]: https://www.roblox.com/library/9486684823 -[sift/itch.io]: https://cxmeel.itch.io/sift -[sift/npm]: https://npmjs.com/package/@rbxts/sift - -Sift is available from [Wally][sift/wally], [Itch.io][sift/itch.io], the [Roblox Library][sift/roblox], and [GitHub releases][sift/releases]. - -While Sift is 100% free and open source, if you feel like sponsoring, Sift is also available on [Itch.io][sift/itch.io]. - -### Wally - -Wally is a CLI package manager (much like NPM, Yarn or Cargo) for Roblox by @UpliftGames. Find out more at https://github.com/upliftgames/wally. - -```toml -# wally.toml - -[dependencies] -Sift = "cxmeel/sift@=0.0.1" -``` - -```shell -$ wally install -``` - -### TypeScript - -v0.0.1 of Sift includes TypeScript definitions. This means Sift is now compatible with roblox-ts. Refer to the Luau docs for API details. - -```shell -$ npm install @rbxts/sift -``` - -[View on NPM →][sift/npm] - -```ts -// example.ts -import Sift from "@rbxts/sift" - -Sift.Dictionary.merge({ a: 1, c: 2 }, { b: 3, c: Sift.None }) // { a: 1, b: 3 } -``` - -Alternatively, you can use tree-shaking to access the modules directly. - -```ts -// example.ts -import { Dictionary, None } from "@rbxts/sift" - -Dictionary.merge({ a: 1, c: 2 }, { b: 3, c: None }) // { a: 1, b: 3 } -``` - -### Manual Installation - -Grab a copy [from the Roblox Library][sift/roblox] or [GitHub releases][sift/releases], and drop it into Studio. The Sift model file can be synced in using Rojo. diff --git a/package.json b/package.json index 9591aca..4b791aa 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,16 @@ { "name": "@rbxts/sift", - "version": "0.0.8", + "version": "0.1.0", "description": "Immutable data library for Luau", "main": "out/init.lua", - "types": "out/index.d.ts", + "types": "@types/index.d.ts", "publishConfig": { "access": "public" }, "scripts": { "build": "rbxtsc --type=package --rojo=''", "watch": "rbxtsc -w", - "prepublishOnly": "npm run build", - "prepare": "husky install" + "prepublishOnly": "npm run build" }, "repository": { "type": "git", diff --git a/sourcemap.json b/sourcemap.json deleted file mode 100644 index a41e6c4..0000000 --- a/sourcemap.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"Sift","className":"ModuleScript","filePaths":["src\\init.luau","default.project.json"],"children":[{"name":"Array","className":"ModuleScript","filePaths":["src\\Array\\init.luau"],"children":[{"name":"concatDeep","className":"ModuleScript","filePaths":["src\\Array\\concatDeep.luau"]},{"name":"copy","className":"ModuleScript","filePaths":["src\\Array\\copy.luau"]},{"name":"copyDeep","className":"ModuleScript","filePaths":["src\\Array\\copyDeep.luau"]},{"name":"count","className":"ModuleScript","filePaths":["src\\Array\\count.luau"]},{"name":"create","className":"ModuleScript","filePaths":["src\\Array\\create.luau"]},{"name":"difference","className":"ModuleScript","filePaths":["src\\Array\\difference.luau"]},{"name":"differenceSymmetric","className":"ModuleScript","filePaths":["src\\Array\\differenceSymmetric.luau"]},{"name":"equals","className":"ModuleScript","filePaths":["src\\Array\\equals.luau"]},{"name":"equalsDeep","className":"ModuleScript","filePaths":["src\\Array\\equalsDeep.luau"]},{"name":"every","className":"ModuleScript","filePaths":["src\\Array\\every.luau"]},{"name":"filter","className":"ModuleScript","filePaths":["src\\Array\\filter.luau"]},{"name":"find","className":"ModuleScript","filePaths":["src\\Array\\find.luau"]},{"name":"findLast","className":"ModuleScript","filePaths":["src\\Array\\findLast.luau"]},{"name":"findWhere","className":"ModuleScript","filePaths":["src\\Array\\findWhere.luau"]},{"name":"findWhereLast","className":"ModuleScript","filePaths":["src\\Array\\findWhereLast.luau"]},{"name":"first","className":"ModuleScript","filePaths":["src\\Array\\first.luau"]},{"name":"flatten","className":"ModuleScript","filePaths":["src\\Array\\flatten.luau"]},{"name":"freeze","className":"ModuleScript","filePaths":["src\\Array\\freeze.luau"]},{"name":"freezeDeep","className":"ModuleScript","filePaths":["src\\Array\\freezeDeep.luau"]},{"name":"includes","className":"ModuleScript","filePaths":["src\\Array\\includes.luau"]},{"name":"insert","className":"ModuleScript","filePaths":["src\\Array\\insert.luau"]},{"name":"is","className":"ModuleScript","filePaths":["src\\Array\\is.luau"]},{"name":"last","className":"ModuleScript","filePaths":["src\\Array\\last.luau"]},{"name":"map","className":"ModuleScript","filePaths":["src\\Array\\map.luau"]},{"name":"pop","className":"ModuleScript","filePaths":["src\\Array\\pop.luau"]},{"name":"push","className":"ModuleScript","filePaths":["src\\Array\\push.luau"]},{"name":"reduce","className":"ModuleScript","filePaths":["src\\Array\\reduce.luau"]},{"name":"reduceRight","className":"ModuleScript","filePaths":["src\\Array\\reduceRight.luau"]},{"name":"removeIndex","className":"ModuleScript","filePaths":["src\\Array\\removeIndex.luau"]},{"name":"removeValues","className":"ModuleScript","filePaths":["src\\Array\\removeValues.luau"]},{"name":"reverse","className":"ModuleScript","filePaths":["src\\Array\\reverse.luau"]},{"name":"slice","className":"ModuleScript","filePaths":["src\\Array\\slice.luau"]},{"name":"update","className":"ModuleScript","filePaths":["src\\Array\\update.luau"]},{"name":"zip","className":"ModuleScript","filePaths":["src\\Array\\zip.luau"]},{"name":"zipAll","className":"ModuleScript","filePaths":["src\\Array\\zipAll.luau"]},{"name":"at","className":"ModuleScript","filePaths":["src\\Array\\at.luau"]},{"name":"concat","className":"ModuleScript","filePaths":["src\\Array\\concat.luau"]},{"name":"removeIndices","className":"ModuleScript","filePaths":["src\\Array\\removeIndices.luau"]},{"name":"removeValue","className":"ModuleScript","filePaths":["src\\Array\\removeValue.luau"]},{"name":"set","className":"ModuleScript","filePaths":["src\\Array\\set.luau"]},{"name":"shift","className":"ModuleScript","filePaths":["src\\Array\\shift.luau"]},{"name":"shuffle","className":"ModuleScript","filePaths":["src\\Array\\shuffle.luau"]},{"name":"some","className":"ModuleScript","filePaths":["src\\Array\\some.luau"]},{"name":"sort","className":"ModuleScript","filePaths":["src\\Array\\sort.luau"]},{"name":"splice","className":"ModuleScript","filePaths":["src\\Array\\splice.luau"]},{"name":"toSet","className":"ModuleScript","filePaths":["src\\Array\\toSet.luau"]},{"name":"unshift","className":"ModuleScript","filePaths":["src\\Array\\unshift.luau"]}]},{"name":"Dictionary","className":"ModuleScript","filePaths":["src\\Dictionary\\init.luau"],"children":[{"name":"copyDeep","className":"ModuleScript","filePaths":["src\\Dictionary\\copyDeep.luau"]},{"name":"count","className":"ModuleScript","filePaths":["src\\Dictionary\\count.luau"]},{"name":"entries","className":"ModuleScript","filePaths":["src\\Dictionary\\entries.luau"]},{"name":"equals","className":"ModuleScript","filePaths":["src\\Dictionary\\equals.luau"]},{"name":"equalsDeep","className":"ModuleScript","filePaths":["src\\Dictionary\\equalsDeep.luau"]},{"name":"every","className":"ModuleScript","filePaths":["src\\Dictionary\\every.luau"]},{"name":"filter","className":"ModuleScript","filePaths":["src\\Dictionary\\filter.luau"]},{"name":"flatten","className":"ModuleScript","filePaths":["src\\Dictionary\\flatten.luau"]},{"name":"flip","className":"ModuleScript","filePaths":["src\\Dictionary\\flip.luau"]},{"name":"freeze","className":"ModuleScript","filePaths":["src\\Dictionary\\freeze.luau"]},{"name":"freezeDeep","className":"ModuleScript","filePaths":["src\\Dictionary\\freezeDeep.luau"]},{"name":"fromArrays","className":"ModuleScript","filePaths":["src\\Dictionary\\fromArrays.luau"]},{"name":"fromEntries","className":"ModuleScript","filePaths":["src\\Dictionary\\fromEntries.luau"]},{"name":"has","className":"ModuleScript","filePaths":["src\\Dictionary\\has.luau"]},{"name":"includes","className":"ModuleScript","filePaths":["src\\Dictionary\\includes.luau"]},{"name":"keys","className":"ModuleScript","filePaths":["src\\Dictionary\\keys.luau"]},{"name":"map","className":"ModuleScript","filePaths":["src\\Dictionary\\map.luau"]},{"name":"merge","className":"ModuleScript","filePaths":["src\\Dictionary\\merge.luau"]},{"name":"mergeDeep","className":"ModuleScript","filePaths":["src\\Dictionary\\mergeDeep.luau"]},{"name":"removeKey","className":"ModuleScript","filePaths":["src\\Dictionary\\removeKey.luau"]},{"name":"removeKeys","className":"ModuleScript","filePaths":["src\\Dictionary\\removeKeys.luau"]},{"name":"removeValue","className":"ModuleScript","filePaths":["src\\Dictionary\\removeValue.luau"]},{"name":"removeValues","className":"ModuleScript","filePaths":["src\\Dictionary\\removeValues.luau"]},{"name":"set","className":"ModuleScript","filePaths":["src\\Dictionary\\set.luau"]},{"name":"some","className":"ModuleScript","filePaths":["src\\Dictionary\\some.luau"]},{"name":"update","className":"ModuleScript","filePaths":["src\\Dictionary\\update.luau"]},{"name":"values","className":"ModuleScript","filePaths":["src\\Dictionary\\values.luau"]},{"name":"withKeys","className":"ModuleScript","filePaths":["src\\Dictionary\\withKeys.luau"]},{"name":"copy","className":"ModuleScript","filePaths":["src\\Dictionary\\copy.luau"]}]},{"name":"Set","className":"ModuleScript","filePaths":["src\\Set\\init.luau"],"children":[{"name":"add","className":"ModuleScript","filePaths":["src\\Set\\add.luau"]},{"name":"copy","className":"ModuleScript","filePaths":["src\\Set\\copy.luau"]},{"name":"count","className":"ModuleScript","filePaths":["src\\Set\\count.luau"]},{"name":"delete","className":"ModuleScript","filePaths":["src\\Set\\delete.luau"]},{"name":"difference","className":"ModuleScript","filePaths":["src\\Set\\difference.luau"]},{"name":"differenceSymmetric","className":"ModuleScript","filePaths":["src\\Set\\differenceSymmetric.luau"]},{"name":"filter","className":"ModuleScript","filePaths":["src\\Set\\filter.luau"]},{"name":"fromArray","className":"ModuleScript","filePaths":["src\\Set\\fromArray.luau"]},{"name":"has","className":"ModuleScript","filePaths":["src\\Set\\has.luau"]},{"name":"intersection","className":"ModuleScript","filePaths":["src\\Set\\intersection.luau"]},{"name":"isSubset","className":"ModuleScript","filePaths":["src\\Set\\isSubset.luau"]},{"name":"isSuperset","className":"ModuleScript","filePaths":["src\\Set\\isSuperset.luau"]},{"name":"map","className":"ModuleScript","filePaths":["src\\Set\\map.luau"]},{"name":"merge","className":"ModuleScript","filePaths":["src\\Set\\merge.luau"]},{"name":"toArray","className":"ModuleScript","filePaths":["src\\Set\\toArray.luau"]}]},{"name":"Util","className":"ModuleScript","filePaths":["src\\Util\\init.luau"],"children":[{"name":"equalObjects","className":"ModuleScript","filePaths":["src\\Util\\equalObjects.luau"]},{"name":"func","className":"ModuleScript","filePaths":["src\\Util\\func.luau"]},{"name":"isEmpty","className":"ModuleScript","filePaths":["src\\Util\\isEmpty.luau"]}]},{"name":"Types","className":"ModuleScript","filePaths":["src\\Types.luau"]},{"name":"None","className":"ModuleScript","filePaths":["src\\None.luau"]}]} \ No newline at end of file diff --git a/src/Array/at.luau b/src/Array/at.luau index b7cdbd5..dbe90fc 100644 --- a/src/Array/at.luau +++ b/src/Array/at.luau @@ -1,26 +1,19 @@ ---!strict --[=[ - @function at - @within Array + @within Array - @param array {T} -- The array to get the value from. - @param index number -- The index to get the value from (can be negative). - @return T -- The value at the given index. + Pick out a value from an array by index, with support for negative indices. + Negative indices are counted from the end of the array. Because Lua uses 1-based indexing, an index of 0 will be treated as 1. - Gets a value from an array at the given index. - - ```lua - local array = { 1, 2, 3 } - - local value = At(array, 1) -- 1 - local value = At(array, 0) -- 3 - ``` + ```lua + at({ "a", "b", "c", "d", "e" }, 2) -- "b" + at({ "a", "b", "c", "d", "e" }, -1) -- "e" + ``` ]=] local function at(array: { T }, index: number): T - local length = #array - - if index < 1 then - index += length + if index == 0 then + index = 1 + elseif index < 0 then + index += #array + 1 end return array[index] diff --git a/src/Array/concat.luau b/src/Array/concat.luau index 76e8abb..1808944 100644 --- a/src/Array/concat.luau +++ b/src/Array/concat.luau @@ -1,46 +1,25 @@ ---!strict -local Sift = script.Parent.Parent - -local None = require(Sift.None) - --[=[ - @function concat - @within Array - - @param ... ...any -- The arrays to concatenate. - @return {T} -- The concatenated array. - - Joins multiple arrays together into a single array. + @within Array - #### Aliases + Concatenates the elements of the given arrays into a new array. - `join`, `merge` + ```lua + local array1 = { 1, 2, 3 } + local array2 = { 4, 5, 6 } - ```lua - local table1 = { 1, 2, 3 } - local table2 = { 4, 5, 6 } - - local new = Concat(table1, table2) -- { 1, 2, 3, 4, 5, 6 } - ``` + concat(array1, array2) -- {1, 2, 3, 4, 5, 6} + ``` ]=] -local function concat(...: any): { T } - local result = {} - - for arrayIndex = 1, select("#", ...) do - local array = select(arrayIndex, ...) - - if type(array) ~= "table" then - continue - end +local function concat(...: { T }) + local out = {} - for _, item in ipairs(array) do - if item ~= None then - table.insert(result, item) - end + for _, array in { ... } do + for _, value in array do + table.insert(out, value) end end - return result + return out end return concat diff --git a/src/Array/concatDeep.luau b/src/Array/concatDeep.luau deleted file mode 100644 index 519b4f2..0000000 --- a/src/Array/concatDeep.luau +++ /dev/null @@ -1,52 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local CopyDeep = require(script.Parent.copyDeep) -local None = require(Sift.None) - ---[=[ - @function concatDeep - @within Array - - @param ... ...any -- The arrays to concatenate. - @return {T} -- The concatenated array. - - Joins multiple arrays together into a single array, with deep copies of all - nested arrays. - - #### Aliases - - `joinDeep`, `mergeDeep` - - ```lua - local table1 = { 1, 2, { 3, 4 } } - local table2 = { 5, 6, { 7, 8 } } - - local new = ConcatDeep(table1, table2) -- { 1, 2, { 3, 4 }, 5, 6, { 7, 8 } } - ``` -]=] -local function concatDeep(...: any): { T } - local result = {} - - for arrayIndex = 1, select("#", ...) do - local array = select(arrayIndex, ...) - - if type(array) ~= "table" then - continue - end - - for _, value in ipairs(array) do - if value ~= None then - if type(value) == "table" then - table.insert(result, CopyDeep(value)) - else - table.insert(result, value) - end - end - end - end - - return result -end - -return concatDeep diff --git a/src/Array/copy.luau b/src/Array/copy.luau index bc31cc6..49a14f7 100644 --- a/src/Array/copy.luau +++ b/src/Array/copy.luau @@ -1,19 +1,13 @@ ---!strict --[=[ - @function copy - @within Array + @within Array + @function copy + @param array { T } + @return { T } - @param array {T} -- The array to copy. - @return {T} -- The copied array. + Returns a shallow copy of the array. Use [Array.copyDeep] to copy nested arrays. - Copies an array. - - ```lua - local array = { 1, 2, 3 } - - local new = Copy(array) -- { 1, 2, 3 } - - print(new == array) -- false - ``` + ```lua + copy({ 1, 2, 3 }) -- { 1, 2, 3 } + ``` ]=] return table.clone diff --git a/src/Array/copyDeep.luau b/src/Array/copyDeep.luau index 36ea759..1e4e203 100644 --- a/src/Array/copyDeep.luau +++ b/src/Array/copyDeep.luau @@ -1,32 +1,25 @@ ---!strict --[=[ - @function copyDeep - @within Array + @within Array - @param array {T} -- The array to copy. - @return {T} -- The copied array. + Returns a deep copy of the given array. This means that all tables within the array are also copied. - Copies an array, with deep copies of all nested arrays. - - ```lua - local array = { 1, 2, 3, { 4, 5 } } - - local result = CopyDeep(array) -- { 1, 2, 3, { 4, 5 } } - - print(result == array) -- false - print(result[4] == array[4]) -- false - ``` + ```lua + local array = {{ 1, 2 }, { 3, 4 }} + copyDeep(array) -- {{ 1, 2 }, { 3, 4 }} + ``` ]=] local function copyDeep(array: { T }): { T } - local result = table.clone(array) + local out: any = {} - for index, value in array do - if type(value) == "table" then - result[index] = copyDeep(value) :: any + for _, value in array do + if typeof(value) == "table" then + table.insert(out, copyDeep(value)) + else + table.insert(out, value) end end - return result + return out end return copyDeep diff --git a/src/Array/count.luau b/src/Array/count.luau index ae569fc..4c63418 100644 --- a/src/Array/count.luau +++ b/src/Array/count.luau @@ -1,38 +1,23 @@ ---!strict -local Sift = script.Parent.Parent - -local Util = require(Sift.Util) - --[=[ - @function count - @within Array + @within Array - @param array {T} -- The array to count the number of items in. - @param predicate? (value: T, index: number, array: {T}) -> any -- The predicate to use to filter the array. - @return number -- The number of items in the array. + Returns the number of elements in the array, optionally filtered by a predicate. - Counts the number of items in an array. + ```lua + local array = { 1, 2, 3, 4, 5 } - ```lua - local array = { 1, 2, 3 } - - local value = Count(array) -- 3 - local value = Count(array, function(item, index) - return item == 2 - end) -- 1 - ``` + count(array) -- 5 + count(array, function(value) + return value > 3 + end) -- 2 + ``` ]=] -local function count( - array: { T }, - predicate: ((value: T, index: number, array: { T }) -> any)? -): number +local function count(array: { T }, predicate: ((value: T, index: number) -> boolean)?): number local counter = 0 - predicate = if type(predicate) == "function" then predicate else Util.func.truthy - - for index, value in ipairs(array) do - if predicate(value, index, array) then - counter += 1 + for index, value in array do + if not predicate or predicate(value, index) then + counter = counter + 1 end end diff --git a/src/Array/create.luau b/src/Array/create.luau index b6e081c..0071060 100644 --- a/src/Array/create.luau +++ b/src/Array/create.luau @@ -1,19 +1,15 @@ ---!strict --[=[ - @function create - @within Array - - @param length number -- The length of the array to create. - @param value? T -- The value to fill the array with. - @return {T} -- The created array. - - Creates an array of the given length, filled with the given value. - This is just a wrapper around `table.create`. - - ```lua - local array = Create(3, "Hello") - - print(array) -- { "Hello", "Hello", "Hello" } - ``` + @within Array + @function create + @param count number + @param value T? + @return { T } + + Creates a new array with `count` elements, each initialized to `value`. + + ```lua + create(3) -- { nil, nil, nil } + create(3, true) -- { true, true, true } + ``` ]=] return table.create diff --git a/src/Array/difference.luau b/src/Array/difference.luau deleted file mode 100644 index 90c5ab5..0000000 --- a/src/Array/difference.luau +++ /dev/null @@ -1,42 +0,0 @@ ---!strict -local T = require(script.Parent.Parent.Types) - -local toSet = require(script.Parent.toSet) -local toArray = require(script.Parent.Parent.Set.toArray) -local setDifference = require(script.Parent.Parent.Set.difference) - ---[=[ - @function difference - @within Array - - @param array Array -- The array to compare. - @param ... ...Array -- The arrays to compare against. - @return Array -- The difference between the arrays. - - Returns an array of values that are in the first array, but not in the other arrays. - - ```lua - local array1 = { "hello", "world" } - local array2 = { "cat", "dog", "hello" } - - local difference = Difference(array1, array2) -- { "world" } - ``` -]=] -local function difference(array: T.Array, ...: T.Array): T.Array - local arraySet = toSet(array) - local otherSets = {} - - for _, nextArray in { ... } do - if typeof(nextArray) ~= "table" then - continue - end - - table.insert(otherSets, toSet(nextArray)) - end - - local differenceSet = setDifference(arraySet, unpack(otherSets)) - - return toArray(differenceSet) -end - -return difference diff --git a/src/Array/difference.luau.todo b/src/Array/difference.luau.todo new file mode 100644 index 0000000..6c399e6 --- /dev/null +++ b/src/Array/difference.luau.todo @@ -0,0 +1 @@ +requires sets diff --git a/src/Array/differenceSymmetric.luau b/src/Array/differenceSymmetric.luau deleted file mode 100644 index 54e358b..0000000 --- a/src/Array/differenceSymmetric.luau +++ /dev/null @@ -1,42 +0,0 @@ ---!strict -local T = require(script.Parent.Parent.Types) - -local toSet = require(script.Parent.toSet) -local toArray = require(script.Parent.Parent.Set.toArray) -local setDifferenceSymmetric = require(script.Parent.Parent.Set.differenceSymmetric) - ---[=[ - @function differenceSymmetric - @within Array - - @param array Array -- The array to compare. - @param ... ...Array -- The arrays to compare against. - @return Array -- The symmetric difference between the arrays. - - Returns an array of values that are in the first array, but not in the other arrays, and vice versa. - - ```lua - local array1 = { "hello", "world" } - local array2 = { "cat", "dog", "hello" } - - local difference = DifferenceSymmetric(array1, array2) -- { "world", "cat", "dog" } - ``` -]=] -local function differenceSymmetric(array: T.Array, ...: T.Array): T.Array - local arraySet = toSet(array) - local otherSets = {} - - for _, nextArray in { ... } do - if typeof(nextArray) ~= "table" then - continue - end - - table.insert(otherSets, toSet(nextArray)) - end - - local differenceSet = setDifferenceSymmetric(arraySet, unpack(otherSets)) - - return toArray(differenceSet) -end - -return differenceSymmetric diff --git a/src/Array/differenceSymmetric.luau.todo b/src/Array/differenceSymmetric.luau.todo new file mode 100644 index 0000000..6c399e6 --- /dev/null +++ b/src/Array/differenceSymmetric.luau.todo @@ -0,0 +1 @@ +requires sets diff --git a/src/Array/equals.luau b/src/Array/equals.luau index c468d79..02a9bb5 100644 --- a/src/Array/equals.luau +++ b/src/Array/equals.luau @@ -1,21 +1,16 @@ ---!strict -local Sift = script.Parent.Parent +local Util = require("@Sift/Util") -local Util = require(Sift.Util) - -local function compare(a, b) - if type(a) ~= "table" or type(b) ~= "table" then +local function compare(a: any, b: any) + if typeof(a) ~= "table" or typeof(b) ~= "table" then return a == b end - local aLength = #a - - if #b ~= aLength then + if #a ~= #b then return false end - for i = 1, aLength do - if a[i] ~= b[i] then + for index, value in a do + if value ~= b[index] then return false end end @@ -24,35 +19,27 @@ local function compare(a, b) end --[=[ - @function equals - @within Array + @within Array - @param ... ...{any} -- The arrays to compare. - @return boolean -- Whether the arrays are equal. + Returns whether or not all of the given arrays are equal to each other. - Compares two arrays for equality. + ```lua + local array1 = { 1, 2, 3 } + local array2 = { 1, 2, 3 } - ```lua - local array = { 1, 2, 3 } - local other = { 1, 2, 3 } - - local value = Equals(array, other) -- true - local value = Equals(array, other, { 1, 2, 3 }) -- true - local value = Equals(array, other, { 1, 2, 4 }) -- false - ``` + equals(array1, array2) -- true + ``` ]=] -local function equals(...: { T }): boolean - if Util.equalObjects(...) then +local function equals(...: any): boolean + if Util.areEqual(...) then return true end - local totalArgs = select("#", ...) - local firstItem = select(1, ...) - - for i = 2, totalArgs do - local item = select(i, ...) + local args = { ... } + local first = table.remove(args, 1) - if not compare(firstItem, item) then + for _, array in args do + if not compare(first, array) then return false end end diff --git a/src/Array/equalsDeep.luau b/src/Array/equalsDeep.luau index 3e8225a..7fa3628 100644 --- a/src/Array/equalsDeep.luau +++ b/src/Array/equalsDeep.luau @@ -1,21 +1,16 @@ ---!strict -local Sift = script.Parent.Parent +local Util = require("@Sift/Util") -local Util = require(Sift.Util) - -local function compareDeep(a, b) - if type(a) ~= "table" or type(b) ~= "table" then +local function compare(a: any, b: any) + if typeof(a) ~= "table" or typeof(b) ~= "table" then return a == b end - local aLength = #a - - if #b ~= aLength then + if #a ~= #b then return false end - for i = 1, aLength do - if not compareDeep(a[i], b[i]) then + for index, value in a do + if not compare(value, b[index]) then return false end end @@ -24,35 +19,27 @@ local function compareDeep(a, b) end --[=[ - @function equalsDeep - @within Array + @within Array - @param ... ...{any} -- The arrays to compare. - @return boolean -- Whether the arrays are equal. + Returns whether or not all of the provided values are deeply equal to each other. Use this function to compare nested arrays. - Compares two arrays for equality using deep comparison. + ```lua + local array1 = {{ 1, 2 }, { 3, 4 }} + local array2 = {{ 1, 2 }, { 4, 5 }} - ```lua - local array = { 1, 2, 3, { 4, 5 } } - local other = { 1, 2, 3, { 4, 5 } } - - local value = EqualsDeep(array, other) -- true - local value = EqualsDeep(array, other, { 1, 2, 3, { 4, 5 } }) -- true - local value = EqualsDeep(array, other, { 1, 2, 3, { 4, 6 } }) -- false - ``` + equalsDeep(array1, array2) -- false + ``` ]=] -local function equalsDeep(...: { T }): boolean - if Util.equalObjects(...) then +local function equalsDeep(...: any): boolean + if Util.areEqual(...) then return true end - local totalArgs = select("#", ...) - local firstItem = select(1, ...) - - for i = 2, totalArgs do - local item = select(i, ...) + local args = { ... } + local first = table.remove(args, 1) - if not compareDeep(firstItem, item) then + for _, value in args do + if not compare(first, value) then return false end end diff --git a/src/Array/every.luau b/src/Array/every.luau index d42399e..6548526 100644 --- a/src/Array/every.luau +++ b/src/Array/every.luau @@ -1,32 +1,17 @@ ---!strict --[=[ - @function every - @within Array + @within Array - @param array {T} -- The array to check. - @param predicate (value: T, index: number, array: {T}) -> any -- The predicate to use to check the array. - @return boolean -- Whether every item in the array passes the predicate. + Returns `true` if every element in the array passes the test implemented by the provided function. Otherwise, it returns `false`. - Checks whether every item in the array passes the predicate. - - ```lua - local array = { 1, 2, 3 } - - local value = Every(array, function(item, index) - return item > 0 - end) -- true - - local value = Every(array, function(item, index) - return item > 1 - end) -- false - ``` + ```lua + every({ 1, 2, 3, 4, 5 }, function(value) + return value > 0 + }) -- true + ``` ]=] -local function every( - array: { T }, - predicate: (value: T, index: number, array: { T }) -> any -): boolean - for index, value in ipairs(array) do - if not predicate(value, index, array) then +local function every(array: { T }, predicate: (value: T, index: number) -> boolean): boolean + for index, value in array do + if not predicate(value, index) then return false end end diff --git a/src/Array/filter.luau b/src/Array/filter.luau index 877b98c..cdbb1ca 100644 --- a/src/Array/filter.luau +++ b/src/Array/filter.luau @@ -1,43 +1,23 @@ ---!strict -local Sift = script.Parent.Parent - -local Util = require(Sift.Util) - --[=[ - @function filter - @within Array - - @param array {T} -- The array to filter. - @param filterer? (value: T, index: number, array: {T}) -> any -- The callback to use to filter the array. - @return {T} -- The filtered array. + @within Array - Filters an array using a filterer callback. Any items that do not pass the filterer will be removed from the array. + Filters out elements from an array based on a filter function. The filter function should return `true` to keep the element, and `false` to remove it. - If no filterer is provided, all items will be kept. - - ```lua - local array = { 1, 2, 3 } - - local result = Filter(array, function(item, index) - return item > 1 - end) -- { 2, 3 } - ``` + ```lua + filter({ 1, 2, 3, 4, 5}, function(value) + return value > 3 + end) -- { 4, 5 } ]=] -local function filter( - array: { T }, - predicate: ((value: T, index: number, array: { T }) -> boolean?)? -): { T } - local result = {} - - predicate = if type(predicate) == "function" then predicate else Util.func.truthy +local function filter(array: { T }, filterer: (value: T, index: number) -> boolean): { T } + local out = {} - for index, value in ipairs(array) do - if predicate(value, index, array) then - table.insert(result, value) + for index, value in array do + if filterer(value, index) then + table.insert(out, value) end end - return result + return out end return filter diff --git a/src/Array/find.luau b/src/Array/find.luau index 5bca288..209d0f5 100644 --- a/src/Array/find.luau +++ b/src/Array/find.luau @@ -1,31 +1,22 @@ ---!strict --[=[ - @function find - @within Array + @within Array - @param array {T} -- The array to search. - @param value? any -- The value to search for. - @param from? number -- The index to start searching from. - @return number? -- The index of the first item in the array that matches the value. + Returns the index of the first occurrence of a value in an array, or `nil` if the value is not found. The search starts at the optional `from` index. If `from` is negative, it is treated as an offset from the end of the array. - Finds the index of the first item in the array that matches the value. This is - mostly a wrapper around `table.find`, with the ability to specify a negative - number as the start index (to search relative to the end of the array). + ```lua + local array = { "a", "b", "c", "a", "b" } - #### Aliases - `indexOf` - - ```lua - local array = { "hello", "world", "hello" } - - local index = Find(array, "hello") -- 1 - local index = Find(array, "hello", 2) -- 3 - ``` + find(array, "a") -- 1 + find(array, "a", 2) -- 4 + find(array, "b", -2) -- 5 + ``` ]=] -local function find(array: { T }, value: any?, from: number?): number? - local length = #array - - from = if type(from) == "number" then if from < 1 then length + from else from else 1 +local function find(array: { T }, value: T, from: number?): number? + if from == 0 then + from = 1 + elseif from and from < 0 then + from += #array + 1 + end return table.find(array, value, from) end diff --git a/src/Array/findLast.luau b/src/Array/findLast.luau index 5755fda..f294068 100644 --- a/src/Array/findLast.luau +++ b/src/Array/findLast.luau @@ -1,34 +1,30 @@ ---!strict --[=[ - @function findLast - @within Array + @within Array - @param array {T} -- The array to search. - @param value? any -- The value to search for. - @param from? number -- The index to start searching from. - @return number? -- The index of the last item in the array that matches the value. + Returns the last index at which a given element can be found in the array, or `nil` if it is not present. The array is searched backwards, starting at the optional `from` index. If `from` is negative, it is used as the offset from the end of the array. - Finds the index of the last item in the array that matches the value. + ```lua + local array = { "a", "b", "c", "a", "b" } - ```lua - local array = { "hello", "world", "hello" } - - local index = FindLast(array, "hello") -- 3 - local index = FindLast(array, "hello", 2) -- 1 - ``` + findLast(array, "b") -- 5 + findLast(array, "b", 3) -- 2 + findLast(array, "b", -3) -- 2 + ``` ]=] -local function findLast(array: { T }, value: any?, from: number?): number? - local length = #array - - from = if type(from) == "number" then if from < 1 then length + from else from else length +local function findLast(array: { T }, value: T, from: number?): number? + if from == 0 then + from = 1 + elseif from and from < 0 then + from += #array + 1 + end - for index = from, 1, -1 do - if array[index] == value then - return index + for i = from or #array, 1, -1 do + if array[i] == value then + return i end end - return + return nil end return findLast diff --git a/src/Array/findWhere.luau b/src/Array/findWhere.luau index a48be9c..4387895 100644 --- a/src/Array/findWhere.luau +++ b/src/Array/findWhere.luau @@ -1,39 +1,32 @@ ---!strict --[=[ - @function findWhere - @within Array + @within Array - @param array {T} -- The array to search. - @param predicate (value: T, index: number, array: {T}) -> any -- The predicate to use to check the array. - @param from? number -- The index to start searching from. - @return number -- The index of the first item in the array that matches the predicate. + Returns the index of the first element in the array that satisfies the provided testing function. Otherwise, it returns `nil`. - Finds the index of the first item in the array that passes the predicate. - - ```lua - local array = { 1, 2, 3 } - - local index = FindWhere(array, function(item, index) - return item > 1 - end) -- 2 - ``` + ```lua + findWhere({ 1, 2, 3, 4, 5 }, function(value) + return value % 2 == 0 + end) -- 2 + ``` ]=] local function findWhere( array: { T }, - predicate: (value: T, index: number, array: { T }) -> any, + predicate: (value: T, index: number) -> boolean, from: number? ): number? - local length = #array - - from = if type(from) == "number" then if from < 1 then length + from else from else 1 + if from == 0 then + from = 1 + elseif from and from < 0 then + from += #array + 1 + end - for index = from, #array do - if predicate(array[index], index, array) then + for index = from or 1, #array do + if predicate(array[index], index) then return index end end - return + return nil end return findWhere diff --git a/src/Array/findWhereLast.luau b/src/Array/findWhereLast.luau index aff4c38..d051972 100644 --- a/src/Array/findWhereLast.luau +++ b/src/Array/findWhereLast.luau @@ -1,43 +1,32 @@ ---!strict --[=[ - @function findWhereLast - @within Array + @within Array - @param array {T} -- The array to search. - @param predicate (value: T, index: number, array: {T}) -> any -- The predicate to use to check the array. - @param from? number -- The index to start searching from. - @return number -- The index of the last item in the array that matches the predicate. + Returns the index of the last element in the array that satisfies the provided testing function. Otherwise, it returns `nil`. - Finds the index of the last item in the array that passes the predicate. - - ```lua - local array = { "hello", "world", "hello" } - - local index = FindWhereLast(array, function(item, index) - return item == "hello" - end) -- 3 - - local index = FindWhereLast(array, function(item, index) - return item == "hello" - end, 2) -- 1 - ``` + ```lua + findWhereLast({ 1, 2, 3, 4, 5 }, function(value) + return value % 2 == 0 + end) -- 4 + ``` ]=] local function findWhereLast( array: { T }, - predicate: (value: T, index: number, array: { T }) -> any, + predicate: (value: T, index: number) -> boolean, from: number? ): number? - local length = #array - - from = if type(from) == "number" then if from < 1 then length + from else from else length + if from == 0 then + from = 1 + elseif from and from < 0 then + from += #array + 1 + end - for index = from, 1, -1 do - if predicate(array[index], index, array) then + for index = from or #array, 1, -1 do + if predicate(array[index], index) then return index end end - return + return nil end return findWhereLast diff --git a/src/Array/first.luau b/src/Array/first.luau index 84304b4..b992f48 100644 --- a/src/Array/first.luau +++ b/src/Array/first.luau @@ -1,23 +1,16 @@ ---!strict -local At = require(script.Parent.at) +local at = require("./at") --[=[ - @function first - @within Array + @within Array - @param array {T} -- The array to get the first item from. - @return T -- The first item in the array. + Returns the first element of an array. - Gets the first item in the array. - - ```lua - local array = { 1, 2, 3 } - - local value = First(array) -- 1 - ``` + ```lua + first({ "a", "b", "c" }) -- "a" + ``` ]=] local function first(array: { T }): T - return At(array, 1) + return at(array, 1) end return first diff --git a/src/Array/flatten.luau b/src/Array/flatten.luau index cf5b561..88aaa2a 100644 --- a/src/Array/flatten.luau +++ b/src/Array/flatten.luau @@ -1,44 +1,37 @@ ---!strict +local INF = newproxy(false) + --[=[ - @function flatten - @within Array - - @param array {T} -- The array to flatten. - @param depth? number -- The depth to flatten the array to. - @return {T} -- The flattened array. - - Flattens an array. If depth is not specified, it will flatten - the array as far as it can go. - - ```lua - local array = { - { 1, 2, 3 }, - { 4, 5, 6 }, - { 7, { 8, 9 } }, - } - - local new = Flatten(array) -- { 1, 2, 3, 4, 5, 6, 7, 8, 9 } - local new = Flatten(array, 1) -- { 1, 2, 3, 4, 5, 6, 7, { 8, 9 } } - ``` + @within Array + + Flattens an array of arrays into a single array. The `depth` parameter specifies the depth of the flattening. If `depth` is not specified, the array is flattened as much as possible. + + ```lua + local array = { 1, { 2, 3, { 4, 5 }}, 6 } + + flatten(array) -- { 1, 2, 3, 4, 5, 6 } + flatten(array, 1) -- { 1, 2, 3, { 4, 5 }, 6 } + ``` ]=] local function flatten(array: { T }, depth: number?): { T } - depth = if type(depth) == "number" then depth else math.huge + local withDepth = depth or INF + local out = {} - local result = {} + for _, value in array do + if typeof(value) == "table" and (withDepth == INF or withDepth > 0) then + local useDepth = withDepth == INF and INF or withDepth - 1 + local nested = flatten(value, useDepth) - for _, value in ipairs(array) do - if type(value) == "table" and depth > 0 then - local nested = flatten(value, depth - 1) - - for _, nestedValue in ipairs(nested) do - table.insert(result, nestedValue) + for _, nestedValue in nested do + table.insert(out, nestedValue) end - else - table.insert(result, value) + + continue end + + table.insert(out, value) end - return result + return out end return flatten diff --git a/src/Array/freeze.luau b/src/Array/freeze.luau index 42963a4..478aebb 100644 --- a/src/Array/freeze.luau +++ b/src/Array/freeze.luau @@ -1,30 +1,21 @@ ---!strict -local Copy = require(script.Parent.copy) +local copy = require("./copy") --[=[ - @function freeze - @within Array + @within Array - @param array {T} -- The array to freeze. - @return {T} -- The frozen array. + Returns a shallow copy of the array that is frozen. This means that the array cannot be modified in any way; i.e. it is read-only. Use [Array.freezeDeep] to freeze nested arrays as well. - Freezes the top level of the array, making it read-only. + ```lua + local frozen = freeze({ "anna", "elsa", "kristoff" }) - ```lua - local array = { 1, 2, 3, { 4, 5, 6 } } - - local new = Freeze(array) - - new[1] = 4 -- error! - new[4][1] = 7 -- still works! - ``` + table.insert(frozen, "olaf") -- error! + frozen[4] = "jorgen" -- error! + frozen[2] = "sven" -- error! + ``` ]=] local function freeze(array: { T }): { T } - local new = Copy(array) - - table.freeze(new) - - return new + local out = copy(array) + return table.freeze(out) end return freeze diff --git a/src/Array/freezeDeep.luau b/src/Array/freezeDeep.luau index 3b63964..8f3bbed 100644 --- a/src/Array/freezeDeep.luau +++ b/src/Array/freezeDeep.luau @@ -1,39 +1,29 @@ ---!strict --[=[ - @function freezeDeep - @within Array + @within Array - @param array {T} -- The array to freeze. - @return {T} -- The frozen array. + Recursively freezes an array and its nested arrays. Using [Array.freeze] will only freeze the top level of the array, leaving nested arrays mutable. - Freezes the entire array, making it read-only, including all - nested arrays. + ```lua + local frozen = freezeDeep({ 1, 2, { 3, 4, { 5, 6 }}}) - ```lua - local array = { 1, 2, 3, { 4, 5, 6 } } - - local new = FreezeDeep(array) - - new[1] = 4 -- error! - new[4][1] = 7 -- error! - ``` + frozen[1] = 2 -- error! + frozen[3][1] = 4 -- error! ]=] local function freezeDeep(array: { T }): { T } - local result = {} + local out: { T } = {} - for i = 1, #array do - local value = array[i] + for _, value in array do + if typeof(value) == "table" then + local nested: any = freezeDeep(value) + table.insert(out, nested) - if type(value) == "table" then - table.insert(result, freezeDeep(value)) - else - table.insert(result, value) + continue end - end - table.freeze(result) + table.insert(out, value) + end - return result + return table.freeze(out) end return freezeDeep diff --git a/src/Array/includes.luau b/src/Array/includes.luau index 7683ec9..e63b46d 100644 --- a/src/Array/includes.luau +++ b/src/Array/includes.luau @@ -1,32 +1,16 @@ ---!strict -local Find = require(script.Parent.find) +local find = require("./find") --[=[ - @function includes - @within Array + @within Array - @param array {T} -- The array to search. - @param value any -- The value to search for. - @param from? number -- The index to start searching from. - @return boolean -- Whether the array contains the value. + Returns `true` if the given value is present in the array, otherwise `false`. - Checks whether the array contains the value. This is a wrapper - around `Find`. - - #### Aliases - - `contains`, `has` - - ```lua - local array = { "hello", "world", "goodbye" } - - local value = Includes(array, "hello") -- true - local value = Includes(array, "sift") -- false - local value = Includes(array, "hello", 2) -- false - ``` + ```lua + includes({ "a", "b", "c" }, "b") -- true + ``` ]=] -local function includes(array: { T }, value: any, from: number?): boolean - return Find(array, value, from) ~= nil +local function includes(array: { T }, value: T, from: number?): boolean + return find(array, value, from) ~= nil end return includes diff --git a/src/Array/init.luau b/src/Array/init.luau index 1fdde97..7d42d9b 100644 --- a/src/Array/init.luau +++ b/src/Array/init.luau @@ -1,82 +1,12 @@ ---!strict --[=[ - @class Array + @class Array - An array is a table consisting of index-value pairs. You don't need to - manually specify the indices when you create an array. + An array is a collection of values, each identified by a numeric index. Luau arrays are 1-based, meaning the first element is at index 1, the second element is at index 2, and so on. - ```lua - local array = { - "hello", - "world", - } - ``` - -

- - #### Aliases - - `List` + ```lua + local array = { 1, 2, 3 } + ``` ]=] -local Array = { - at = require(script.at), - concat = require(script.concat), - concatDeep = require(script.concatDeep), - copy = require(script.copy), - copyDeep = require(script.copyDeep), - count = require(script.count), - create = require(script.create), - difference = require(script.difference), - differenceSymmetric = require(script.differenceSymmetric), - equals = require(script.equals), - equalsDeep = require(script.equalsDeep), - every = require(script.every), - filter = require(script.filter), - find = require(script.find), - findLast = require(script.findLast), - findWhere = require(script.findWhere), - findWhereLast = require(script.findWhereLast), - first = require(script.first), - flatten = require(script.flatten), - freeze = require(script.freeze), - freezeDeep = require(script.freezeDeep), - includes = require(script.includes), - insert = require(script.insert), - is = require(script.is), - last = require(script.last), - map = require(script.map), - pop = require(script.pop), - push = require(script.push), - reduce = require(script.reduce), - reduceRight = require(script.reduceRight), - removeIndex = require(script.removeIndex), - removeIndices = require(script.removeIndices), - removeValue = require(script.removeValue), - removeValues = require(script.removeValues), - reverse = require(script.reverse), - set = require(script.set), - shift = require(script.shift), - shuffle = require(script.shuffle), - slice = require(script.slice), - some = require(script.some), - sort = require(script.sort), - splice = require(script.splice), - toSet = require(script.toSet), - unshift = require(script.unshift), - update = require(script.update), - zip = require(script.zip), - zipAll = require(script.zipAll), -} - -Array.join = Array.concat -Array.merge = Array.concat -Array.joinDeep = Array.concatDeep -Array.mergeDeep = Array.concatDeep -Array.append = Array.push -Array.prepend = Array.unshift -Array.indexOf = Array.find -Array.has = Array.includes -Array.contains = Array.includes -Array.isArray = Array.is +local Array = {} return Array diff --git a/src/Array/insert.luau b/src/Array/insert.luau index 400a129..f6aea5c 100644 --- a/src/Array/insert.luau +++ b/src/Array/insert.luau @@ -1,52 +1,31 @@ ---!strict ---[=[ - @function insert - @within Array - - @param array {T} -- The array to insert the value into. - @param index number -- The index to insert the value at (can be negative). - @param values ...T -- The values to insert. - @return {T} -- The array with the value inserted. +local copy = require("./copy") - Inserts the given values into an array at the given index, shifting all values after it to the right. If the index is negative (or 0), it is counted from the end of the array. +--[=[ + @within Array - If the index to insert at is out of range, the array is not modified. + Inserts the given values into the array at the specified index. - ```lua - local array = { 1, 2, 3 } + ```lua + local array = { "a", "b", "c" } - local newArray = Insert(array, 2, 4) -- { 1, 4, 2, 3 } - ``` + insert(array, 2, "x", "y") -- { "a", "x", "y", "b", "c" } + insert(array, -1, "x", "y") -- { "a", "b", "x", "y", "c" } + ``` ]=] local function insert(array: { T }, index: number, ...: T): { T } - local length = #array - - if index < 1 then - index += length + 1 + if index == 0 then + index = 1 + elseif index < 0 then + index += #array + 1 end - if index > length then - if index > length + 1 then - return array - end - - index = length + 1 - length += 1 - end - - local result = {} - - for i = 1, length do - if i == index then - for _, value in ipairs({ ... }) do - table.insert(result, value) - end - end + local out = copy(array) - table.insert(result, array[i]) + for i = 1, select("#", ...) do + table.insert(out, index + i - 1, select(i, ...)) end - return result + return out end return insert diff --git a/src/Array/is.luau b/src/Array/is.luau index 7c8c90b..144895b 100644 --- a/src/Array/is.luau +++ b/src/Array/is.luau @@ -1,25 +1,17 @@ ---!strict --[=[ - @function is - @within Array + @within Array - @param object any -- The object to check. - @return boolean -- Whether the object is an array. + Checks if `value` is an array. - Checks if the given object is an array. - - ```lua - local array = { 1, 2, 3 } - local dictionary = { hello = "world" } - local mixed = { 1, 2, hello = "world" } - - Array.is(array) -- true - Array.is(dictionary) -- false - Array.is(mixed) -- false - ``` + ```lua + is({ 1, 2, 3 }) -- true + is({ a = 1, b = 2, c = 3 }) -- false + is("hello") -- false + is({}) -- false + ``` ]=] -local function is(object: any): boolean - return typeof(object) == "table" and #object > 0 and next(object, #object) == nil +local function is(value: any): boolean + return typeof(value) == "table" and #value > 0 and next(value, #value) == nil end return is diff --git a/src/Array/last.luau b/src/Array/last.luau index 3bd1a2a..10097ff 100644 --- a/src/Array/last.luau +++ b/src/Array/last.luau @@ -1,23 +1,16 @@ ---!strict -local At = require(script.Parent.at) +local at = require("./at") --[=[ - @function last - @within Array + @within Array - @param array {T} -- The array to get the last element of. - @return T -- The last element of the array. + Returns the last element of an array. - Gets the last element of the array. - - ```lua - local array = { 1, 2, 3 } - - local value = Last(array) -- 3 - ``` + ```lua + last({ "a", "b", "c" }) --> "c" + ``` ]=] local function last(array: { T }): T - return At(array, 0) + return at(array, -1) end return last diff --git a/src/Array/map.luau b/src/Array/map.luau index f9bdb18..d48a1ad 100644 --- a/src/Array/map.luau +++ b/src/Array/map.luau @@ -1,34 +1,28 @@ ---!strict ---[=[ - @function map - @within Array - - @param array {T} -- The array to map. - @param mapper (value: T, index: number, array: {T}) -> U? -- The mapper function. - @return {U} -- The mapped array. +local None = require("@Sift/None") - Maps the array using the mapper function. +--[=[ + @within Array - ```lua - local array = { 1, 2, 3 } + Processes each element of an array with a mapper function and returns a new array with the results. - local new = Map(array, function(value, index) - return value * 2 - end) -- { 2, 4, 6 } - ``` + ```lua + map({ 1, 2, 3, 4, 5 }, function(value) + return value * 2 + end) -- { 2, 4, 6, 8, 10 } + ``` ]=] -local function map(array: { T }, mapper: (value: T, index: number, array: { T }) -> U?): { U } - local mapped = {} +local function map(array: { T }, mapper: (value: T, index: number) -> U?): { U } + local out: { U } = {} - for index, value in ipairs(array) do - local mappedValue = mapper(value, index, array) + for index, value in array do + local mapped = mapper(value, index) - if mappedValue ~= nil then - table.insert(mapped, mappedValue) + if mapped ~= nil and mapped ~= None then + table.insert(out, mapped) end end - return mapped + return out end return map diff --git a/src/Array/partition.luau b/src/Array/partition.luau new file mode 100644 index 0000000..9a9f8a0 --- /dev/null +++ b/src/Array/partition.luau @@ -0,0 +1,30 @@ +--[=[ + @within Array + + Filters an array into two arrays based on a filter function. The first array contains all elements that pass the filter, and the second array contains all elements that fail the filter. + + ```lua + local even, odd = partition({ 1, 2, 3, 4, 5 }, function(value) + return value % 2 == 0 + end) + + -- even: { 2, 4 } + -- odd: { 1, 3, 5 } + ``` +]=] +local function partition(array: { T }, filterer: (value: T, index: number) -> boolean) + local pass = {} + local fail = {} + + for index, value in array do + if filterer(value, index) then + table.insert(pass, value) + else + table.insert(fail, value) + end + end + + return pass, fail +end + +return partition diff --git a/src/Array/pop.luau b/src/Array/pop.luau index 7a42515..c22ee80 100644 --- a/src/Array/pop.luau +++ b/src/Array/pop.luau @@ -1,33 +1,30 @@ ---!strict ---[=[ - @function pop - @within Array +local removeIndices = require("./removeIndices") - @param array {T} -- The array to pop an element from. - @param count? number = 1 -- The number of elements to pop. - @return {T} -- An array with the popped elements removed. +--[=[ + @within Array - Removes an element from the end of the array, and returns - the array with the popped elements removed. + Returns a new array with the last `count` elements removed. If `count` is not provided, it defaults to `1`. - ```lua - local array = { 1, 2, 3 } + ```lua + local array = { 1, 2, 3, 4, 5 } - local new = Pop(array) -- { 1, 2 } - local new = Pop(array, 2) -- { 1 } - ``` + pop(array) -- { 1, 2, 3, 4 } + pop(array, 3) -- { 1, 2 } + ``` ]=] local function pop(array: { T }, count: number?): { T } - local length = #array - local result = {} + local useCount = count or 1 + local indices = {} - count = if type(count) == "number" then count else 1 + if useCount > #array then + return {} + end - for i = 1, length - count do - table.insert(result, array[i]) + for index = 1, useCount do + table.insert(indices, #array - index + 1) end - return result + return removeIndices(array, table.unpack(indices)) end return pop diff --git a/src/Array/push.luau b/src/Array/push.luau index 707d41e..bffe75b 100644 --- a/src/Array/push.luau +++ b/src/Array/push.luau @@ -1,36 +1,16 @@ ---!strict ---[=[ - @function push - @within Array - - @param array {T} -- The array to push an element to. - @param ... ...T -- The elements to push. - @return {T} -- The array with the pushed elements. - - Adds elements to the end of the array. - - #### Aliases +local insert = require("./insert") - `append` +--[=[ + @within Array - ```lua - local array = { 1, 2, 3 } + Returns a new array with the provided values appended to the end. - local new = Push(array, 4, 5, 6) -- { 1, 2, 3, 4, 5, 6 } - ``` + ```lua + push({ 1, 2, 3 }, 4, 5) -- {1, 2, 3, 4, 5} + ``` ]=] local function push(array: { T }, ...: T): { T } - local result = {} - - for _, value in ipairs(array) do - table.insert(result, value) - end - - for _, value in ipairs({ ... }) do - table.insert(result, value) - end - - return result + return insert(array, #array + 1, ...) end return push diff --git a/src/Array/reduce.luau b/src/Array/reduce.luau index d0bfb5e..554019b 100644 --- a/src/Array/reduce.luau +++ b/src/Array/reduce.luau @@ -1,47 +1,34 @@ ---!strict ---[=[ - @function reduce - @within Array - - @param array {T} -- The array to reduce. - @param reducer (accumulator: U, value: T, index: number, array: {T}) -> U -- The reducer to use. - @param initialReduction? U = {T}[1] -- The initial accumulator value. - @return U -- The final accumulator value. +local None = require("@Sift/None") - Reduces the array using the given reducer and initial accumulator value. - If no `initialReduction` value is given, the first item in the array is used. - - ```lua - local array = { 1, 2, 3 } +--[=[ + @within Array - local value = Reduce(array, function(accumulator, item, index) - return accumulator - item - end) -- -4 + Reduces an array to a single value using a reducer function. - local value = Reduce(array, function(accumulator, item, index) - table.insert(accumulator, item) - return accumulator - end, {}) -- { 1, 2, 3 } - ``` + ```lua + reduce({ 1, 2, 3 }, function(accumulator, value) + return accumulator + value + end) -- 6 + ``` ]=] local function reduce( array: { T }, - reducer: (accumulator: U, value: T, index: number, array: { T }) -> U, - initReduction: U? + reducer: (accumulator: U, value: T, index: number) -> U, + initAccumulator: U? ): U - local result = initReduction + local out = initAccumulator :: U local start = 1 - if result == nil then - result = array[1] + if out == nil or out == None then + out = array[1] :: any start = 2 end for index = start, #array do - result = reducer(result, array[index], index, array) + out = reducer(out, array[index], index) end - return result + return out end return reduce diff --git a/src/Array/reduceRight.luau b/src/Array/reduceRight.luau index 7d79e77..f39620b 100644 --- a/src/Array/reduceRight.luau +++ b/src/Array/reduceRight.luau @@ -1,48 +1,34 @@ ---!strict ---[=[ - @function reduceRight - @within Array - - @param array {T} -- The array to reduce. - @param reducer (accumulator: U, value: T, index: number, array: {T}) -> U -- The reducer to use. - @param initialReduction? U = {T}[#{T}] -- The initial accumulator value. - @return U -- The final accumulator value. +local None = require("@Sift/None") - Reduces the array using the given reducer and initial accumulator value, - starting from the end of the array. If no `initialReduction` value is given, - the last item in the array is used. - - ```lua - local array = { 1, 2, 3 } +--[=[ + @within Array - local value = ReduceRight(array, function(accumulator, item, index) - return accumulator - item - end) -- 0 + Reduces an array into a single value from end to start. - local value = ReduceRight(array, function(accumulator, item, index) - table.insert(accumulator, item) - return accumulator - end, {}) -- { 3, 2, 1 } - ``` + ```lua + reduceRight({ 1, 2, 3 }, function(accumulator, value) + return accumulator - value + end) -- 0 + ``` ]=] local function reduceRight( array: { T }, - reducer: (accumulator: U, value: T, index: number, array: { T }) -> U, - initReduction: U? + reducer: (accumulator: U, value: T, index: number) -> U, + initAccumulator: U? ): U - local result = initReduction + local out = initAccumulator :: U local start = #array - if result == nil then - result = array[start] + if out == nil or out == None then + out = array[start] :: any start -= 1 end for index = start, 1, -1 do - result = reducer(result, array[index], index, array) + out = reducer(out, array[index], index) end - return result + return out end return reduceRight diff --git a/src/Array/removeIndex.luau b/src/Array/removeIndex.luau index c98a8cc..a7cbabc 100644 --- a/src/Array/removeIndex.luau +++ b/src/Array/removeIndex.luau @@ -1,36 +1,16 @@ ---!strict ---[=[ - @function removeIndex - @within Array - - @param array {T} -- The array to remove the value from. - @param index number -- The index to remove the value from (can be negative). - @return {T} -- The array with the value removed. +local removeIndices = require("./removeIndices") - Removes a value from an array at the given index. +--[=[ + @within Array - ```lua - local array = { 1, 2, 3 } + Returns a new array with the element at the specified index removed. - local new = RemoveIndex(array, 1) -- { 2, 3 } - local new = RemoveIndex(array, -1) -- { 1, 3 } - ``` + ```lua + removeIndex({ 1, 2, 3 }, 2) -- {1, 3} + ``` ]=] local function removeIndex(array: { T }, index: number): { T } - local length = #array - local result = {} - - if index < 1 then - index += length - end - - for arrIndex, value in ipairs(array) do - if arrIndex ~= index then - table.insert(result, value) - end - end - - return result + return removeIndices(array, index) end return removeIndex diff --git a/src/Array/removeIndices.luau b/src/Array/removeIndices.luau index 8a6f8c8..f3bb844 100644 --- a/src/Array/removeIndices.luau +++ b/src/Array/removeIndices.luau @@ -1,41 +1,36 @@ ---!strict ---[=[ - @function removeIndices - @within Array - - @param array {T} -- The array to remove the indices from. - @param ... ...number -- The indices to remove the values from (can be negative). - @return {T} -- The array with the values removed. +local reduce = require("./reduce") - Removes values from an array at the given indices. +--[=[ + @within Array - ```lua - local array = { 1, 2, 3 } + Returns a new array with the elements at the specified indices removed. - local new = RemoveIndices(array, 1, 2) -- { 3 } - local new = RemoveIndices(array, 0, -1) -- { 1 } - ``` + ```lua + removeIndices({ 1, 2, 3, 4, 5 }, 2, 4) -- {1, 3, 5} + ``` ]=] local function removeIndices(array: { T }, ...: number): { T } - local length = #array - local indices = {} - local result = {} - - for _, index in ipairs({ ... }) do - if index < 1 then - index += length + local indices = reduce({ ... }, function(acc, value) + if value == 0 then + value = 1 + elseif value < 0 then + value += #array + 1 end - indices[index] = true - end + acc[value] = true + + return acc + end, {}) + + local out = {} - for index, value in ipairs(array) do + for index, value in array do if not indices[index] then - table.insert(result, value) + table.insert(out, value) end end - return result + return out end return removeIndices diff --git a/src/Array/removeValue.luau b/src/Array/removeValue.luau index 390c22a..d3b191e 100644 --- a/src/Array/removeValue.luau +++ b/src/Array/removeValue.luau @@ -1,30 +1,16 @@ ---!strict ---[=[ - @function removeValue - @within Array - - @param array {T} -- The array to remove the value from. - @param value T -- The value to remove. - @return {T} -- The array with the value removed. +local removeValues = require("./removeValues") - Removes a value from an array. +--[=[ + @within Array - ```lua - local array = { 1, 2, 3 } + Removes all instances of a value from an array. - local new = RemoveValue(array, 2) -- { 1, 3 } - ``` + ```lua + removeValue({ "a", "b", "c", "a" }, "a") -- { "b", "c" } + ``` ]=] local function removeValue(array: { T }, value: T): { T } - local result = {} - - for _, arrValue in ipairs(array) do - if arrValue ~= value then - table.insert(result, arrValue) - end - end - - return result + return removeValues(array, value) end return removeValue diff --git a/src/Array/removeValues.luau b/src/Array/removeValues.luau index 4a6928e..644b777 100644 --- a/src/Array/removeValues.luau +++ b/src/Array/removeValues.luau @@ -1,33 +1,25 @@ ---!strict -local ToSet = require(script.Parent.toSet) +local filter = require("./filter") +local reduce = require("./reduce") --[=[ - @function removeValues - @within Array + @within Array - @param array {T} -- The array to remove values from. - @param ... T -- The values to remove. - @return {T} -- The array with the values removed. + Removes all instances of the given values from the array. - Removes values from an array. - - ```lua - local array = { "a", "b", "c", "c", "d", "e" } - - local new = RemoveValues(array, "c", "d") -- { "a", "b", "e" } - ``` + ```lua + removeValues({ "a", "a", "c", "b", "c", "a", "d" }, "a", "c") + -- { "b", "d" } + ``` ]=] local function removeValues(array: { T }, ...: T): { T } - local valueSet = ToSet({ ... }) - local result = {} - - for _, value in ipairs(array) do - if not valueSet[value] then - table.insert(result, value) - end - end - - return result + local values = reduce({ ... }, function(acc, value) + acc[value] = true + return acc + end, {}) + + return filter(array, function(value) + return not values[value] + end) end return removeValues diff --git a/src/Array/reverse.luau b/src/Array/reverse.luau index 192be65..64db68d 100644 --- a/src/Array/reverse.luau +++ b/src/Array/reverse.luau @@ -1,27 +1,20 @@ ---!strict --[=[ - @function reverse - @within Array + @within Array - @param array {T} -- The array to reverse. - @return {T} -- The reversed array. + Returns a new array with the elements in reverse order. - Reverses the order of the items in an array. - - ```lua - local array = { 1, 2, 3 } - - local new = Reverse(array) -- { 3, 2, 1 } - ``` + ```lua + reverse({ "a", "b", "c" }) -- { "c", "b", "a" } + ``` ]=] local function reverse(array: { T }): { T } - local result = {} + local out = {} for index = #array, 1, -1 do - table.insert(result, array[index]) + table.insert(out, array[index]) end - return result + return out end return reverse diff --git a/src/Array/set.luau b/src/Array/set.luau index 51b26d6..d8366b8 100644 --- a/src/Array/set.luau +++ b/src/Array/set.luau @@ -1,39 +1,29 @@ ---!strict ---[=[ - @function set - @within Array +local copy = require("./copy") - @param array {T} -- The array to set the value on. - @param index number -- The index to set the value at (can be negative). - @param value T -- The value to set. - @return {T} -- The array with the value set. +--[=[ + @within Array - Sets a value on an array at the given index. + Sets the value at the given index in the array and returns a new array. - ```lua - local array = { 1, 2, 3 } + ```lua + local array = { "a", "b", "c", "d" } - local new = Set(array, 2, 4) -- { 1, 4, 3 } - local new = Set(array, -1, 4) -- { 1, 2, 4 } - ``` + set(array, 2, "z") -- { "a", "z", "c", "d" } + set(array, -1, "x") -- { "a", "b", "c", "x" } + ``` ]=] -local function set(array: { T }, index: number, value: T?): { T } - local length = #array - local result = {} +local function set(array: { T }, index: number, value: T): { T } + local out = copy(array) - if index < 1 then - index += length + if index == 0 then + index = 1 + elseif index < 0 then + index += #out + 1 end - for arrIndex, arrValue in ipairs(array) do - if arrIndex == index then - table.insert(result, value) - else - table.insert(result, arrValue) - end - end + out[index] = value - return result + return out end return set diff --git a/src/Array/shift.luau b/src/Array/shift.luau index 0c55fe6..4858541 100644 --- a/src/Array/shift.luau +++ b/src/Array/shift.luau @@ -1,33 +1,30 @@ ---!strict ---[=[ - @function shift - @within Array +local removeIndices = require("./removeIndices") - @param array {T} -- The array to shift. - @param count? number -- The number of items to shift. - @return {T} -- The shifted array. +--[=[ + @within Array - Removes the first item from an array and returns the array - with the item removed. + Returns a new array with the first `count` elements removed. If `count` is not provided, it defaults to `1`. - ```lua - local array = { 1, 2, 3 } + ```lua + local array = { "a", "b", "c", "d" } - local new = Shift(array) -- { 2, 3 } - local new = Shift(array, 2) -- { 3 } - ``` + shift(array) -- { "b", "c", "d" } + shift(array, 2) -- { "c", "d" } + ``` ]=] local function shift(array: { T }, count: number?): { T } - local length = #array - local result = {} + local useCount = count or 1 + local indices = {} - count = if type(count) == "number" then count + 1 else 2 + if useCount > #array then + return {} + end - for i = count, length do - table.insert(result, array[i]) + for index = #array, useCount, -1 do + table.insert(indices, index) end - return result + return removeIndices(array, table.unpack(indices)) end return shift diff --git a/src/Array/shuffle.luau b/src/Array/shuffle.luau index e237d42..d339e3f 100644 --- a/src/Array/shuffle.luau +++ b/src/Array/shuffle.luau @@ -1,34 +1,28 @@ ---!strict -local Copy = require(script.Parent.copy) +local copy = require("./copy") --[=[ - @function shuffle - @within Array + @within Array - @param array {T} -- The array to shuffle. - @return {T} -- The shuffled array. + Copies an array with a randomized order. - Randomises the order of the items in an array. - - ```lua - local array = { 1, 2, 3 } - - local new = Shuffle(array) -- { 2, 3, 1 } - ``` + ```lua + shuffle({ "a", "b", "c" }) -- { "c", "a", "b" } + ``` ]=] -local function shuffle(array: { T }): { T } - local random = Random.new(os.time() * #array) - local result = Copy(array) +local function shuffle(array: { T }, seed: number?): { T } + math.randomseed(seed or os.clock() * #array) + + local out = copy(array) - for index = #result, 1, -1 do - local randomIndex = random:NextInteger(1, index) - local temp = result[index] + for index = #out, 1, -1 do + local randomIndex = math.random(1, index) + local temp = out[index] - result[index] = result[randomIndex] - result[randomIndex] = temp + out[index] = out[randomIndex] + out[randomIndex] = temp end - return result + return out end return shuffle diff --git a/src/Array/slice.luau b/src/Array/slice.luau index 7d6c20e..14b872f 100644 --- a/src/Array/slice.luau +++ b/src/Array/slice.luau @@ -1,43 +1,39 @@ ---!strict --[=[ - @function slice - @within Array + @within Array - @param array {T} -- The array to slice. - @param from? number -- The index to start from (can be negative). - @param to? number -- The index to end at (can be negative). - @return {T} -- The sliced array. + Returns a slice of an array from `from` to `to` (inclusive). `from` and `to` can be negative, in which case they will be treated as an offset from the end of the array. - Slices an array. + ```lua + local array = { "a", "b", "c", "d", "e", "f" } - ```lua - local array = { 1, 2, 3, 4, 5 } - - local new = Slice(array, 2, 3) -- { 2, 3 } - local new = Slice(array, -2, -1) -- { 3, 4 } - local new = Slice(array, 3) -- { 3, 4, 5 } - ``` + slice(array, 2, 4) -- { "b", "c", "d" } + slice(array, 2, -2) -- { "b", "c", "d", "e" } + ``` ]=] local function slice(array: { T }, from: number?, to: number?): { T } - local length = #array - local result = {} - - from = if type(from) == "number" then from else 1 - to = if type(to) == "number" then to else length + if not from or from == 0 then + from = 1 + elseif from < 0 then + from += #array + 1 + end - if from < 1 then - from += length + if not to or to == 0 then + to = #array + elseif to < 0 then + to += #array + 1 end - if to < 1 then - to += length + if from == to then + return {} end - for i = from, to do - table.insert(result, array[i]) + local out = {} + + for index = from :: number, to :: number do + table.insert(out, array[index]) end - return result + return out end return slice diff --git a/src/Array/some.luau b/src/Array/some.luau index 0c5be36..d456e98 100644 --- a/src/Array/some.luau +++ b/src/Array/some.luau @@ -1,32 +1,17 @@ ---!strict --[=[ - @function some - @within Array + @within Array - @param array {T} -- The array to check. - @param predicate (value: T, index: number, array: {T}) -> any -- The predicate to use to check the array. - @return boolean -- Whether some item in the array passes the predicate. + Returns `true` if at least one element in the array satisfies the provided testing function. Otherwise, `false` is returned. - Checks whether some item in the array passes the predicate. - - ```lua - local array = { 1, 2, 3 } - - local value = Some(array, function(item, index) - return item > 1 - end) -- true - - local value = Some(array, function(item, index) - return item > 3 - end) -- false - ``` + ```lua + some({ 1, 2, 3, 4, 5 }, function(value) + return value % 2 == 0 + end) -- true + ``` ]=] -local function some( - array: { T }, - predicate: (value: T, index: number, array: { T }) -> any -): boolean - for index, value in ipairs(array) do - if predicate(value, index, array) then +local function some(array: { T }, predicate: (value: T, index: number) -> boolean): boolean + for index, value in array do + if predicate(value, index) then return true end end diff --git a/src/Array/sort.luau b/src/Array/sort.luau index 72c6833..e81b552 100644 --- a/src/Array/sort.luau +++ b/src/Array/sort.luau @@ -1,28 +1,18 @@ ---!strict -local Copy = require(script.Parent.copy) +local copy = require("./copy") --[=[ - @function sort - @within Array + @within Array - @param array {T} -- The array to sort. - @param comparator? (a: T, b: T) -> boolean -- The comparator function. - @return {T} -- The sorted array. + Returns a new array with the elements sorted. The optional `comparer` function is used to compare elements. If not provided, the default comparer will be used (ascending order). - Sorts an array. - - ```lua - local array = { "a", "b", "c", "d", "e" } - - local new = Sort(array, function(a, b) - return a > b - end) -- { "e", "d", "c", "b", "a" } - ``` + ```lua + sort({ 3, 1, 2 }) -- { 1, 2, 3 } + sort({ "c", "a", "b" }) -- { "a", "b", "c" } + ``` ]=] -local function sort(array: { T }, comparator: ((firstValue: T, secondValue: T) -> boolean)?): { T } - local result = Copy(array) - - table.sort(result, comparator) +local function sort(array: { T }, comparer: ((a: T, b: T) -> boolean)?): { T } + local result = copy(array) + table.sort(result, comparer) return result end diff --git a/src/Array/splice.luau b/src/Array/splice.luau index e0c4a22..8497dd3 100644 --- a/src/Array/splice.luau +++ b/src/Array/splice.luau @@ -1,52 +1,44 @@ ---!strict --[=[ - @function splice - @within Array + @within Array - @param array {T} -- The array to splice. - @param start? number -- The index to start splicing at (can be negative). - @param end? number -- The index to end splicing at (can be negative). - @param ... ...T -- The values to insert. - @return {T} -- The spliced array. + Returns a new array with elements removed and/or added. The `at` parameter specifies the index at which to start removing or adding elements. The `replaceCount` parameter specifies the number of elements to remove. Finally, the rest of the parameters are the elements to add to the array. - Splices an array. + ```lua + local array = { "a", "b", "c", "d" } - ```lua - local array = { 1, 2, 3, 4, 5 } - - local new = Splice(array, 3, 4, 6, 7) -- { 1, 2, 6, 7, 4, 5 } - local new = Splice(array, -1, 0, 6, 7) -- { 1, 2, 3, 4, 6, 7 } - local new = Splice(array, 4, -1, 6, 7) -- { 1, 2, 3, 6, 7, 5 } - ``` + splice(array, 2, 1, "x", "y", "z") -- { "a", "x", "y", "z", "c", "d" } + splice(array, 2, 0, "x", "y", "z") -- { "a", "x", "y", "z", "b", "c", "d" } + splice(array, 2, 1) -- { "a", "c", "d" } + ``` ]=] -local function splice(array: { T }, from: number?, to: number?, ...: T?): { T } - local length = #array - local result = {} - - from = if type(from) == "number" then from else 1 - to = if type(to) == "number" then to else length +local function splice(array: { T }, at: number?, replaceCount: number?, ...: T?): { T } + local useAt, useReplaceCount = 0, 0 - if from < 1 then - from += length + if not at or at == 0 then + useAt = 1 + elseif at < 0 then + useAt = at + #array + 1 end - if to < 1 then - to += length + if not replaceCount or replaceCount < 0 then + useReplaceCount = 0 end - for index = 1, from - 1 do - table.insert(result, array[index]) + local out = {} + + for index = 1, useAt - 1 do + table.insert(out, array[index]) end - for _, value in ipairs({ ... }) do - table.insert(result, value) + for index = 1, select("#", ...) do + table.insert(out, select(index, ...)) end - for index = to + 1, length do - table.insert(result, array[index]) + for index = useAt + useReplaceCount, #array do + table.insert(out, array[index]) end - return result + return out end return splice diff --git a/src/Array/toSet.luau b/src/Array/toSet.luau index 205774e..bd2ebe1 100644 --- a/src/Array/toSet.luau +++ b/src/Array/toSet.luau @@ -1,30 +1,20 @@ ---!strict -local Sift = script.Parent.Parent -local _T = require(Sift.Types) +local reduce = require("./reduce") --[=[ - @function toSet - @within Array + @within Array - @param array {T} -- The array to convert to a set. - @return Set -- The set. + Converts an array into a set, where each value in the array is a key in the set, and the value is `true`. - Converts an array to a set. - - ```lua - local array = { "a", "b", "b", "c", "d" } - - local set = ToSet(array) -- { a = true, b = true, c = true, d = true } - ``` + ```lua + toSet({ "a", "b", "c", "a", "a", "d" }) + -- { a = true, b = true, c = true, d = true } + ``` ]=] -local function toSet(array: { T }): _T.Set - local set = {} - - for _, value in ipairs(array) do +local function toSet(array: { T }): { [T]: boolean } + return reduce(array, function(set, value) set[value] = true - end - - return set + return set + end, {}) end return toSet diff --git a/src/Array/unshift.luau b/src/Array/unshift.luau index 9e453a2..3cbdf76 100644 --- a/src/Array/unshift.luau +++ b/src/Array/unshift.luau @@ -1,32 +1,10 @@ ---!strict ---[=[ - @function unshift - @within Array - - @param array {T} -- The array to insert the values to. - @param ... ...T -- The values to insert. - @return {T} -- The array with the values inserted. - - Inserts values to the beginning of an array. - - #### Aliases - - `prepend` +local insert = require("./insert") - ```lua - local array = { 1, 2, 3 } - - local new = Unshift(array, 4, 5) -- { 4, 5, 1, 2, 3 } - ``` +--[=[ + @within Array ]=] local function unshift(array: { T }, ...: T): { T } - local result = { ... } - - for _, value in ipairs(array) do - table.insert(result, value) - end - - return result + return insert(array, 1, ...) end return unshift diff --git a/src/Array/update.luau b/src/Array/update.luau index e3e96da..0aac09c 100644 --- a/src/Array/update.luau +++ b/src/Array/update.luau @@ -1,68 +1,43 @@ ---!strict -local Sift = script.Parent.Parent +local None = require("@Sift/None") +local Util = require("@Sift/Util") -local Util = require(Sift.Util) -local Copy = require(script.Parent.copy) - -type Callback = (index: number) -> T -type Updater = (currentValue: T, index: number) -> T - -local function call(callback: Callback, index: number) - if type(callback) == "function" then - return callback(index) - end -end +local copy = require("./copy") --[=[ - @function update - @within Array - - @param array {T} -- The array to update. - @param index number -- The index to update. - @param updater? (value: T, index: number) -> T -- The updater function. - @param callback? (index: number) -> T -- The callback function. - @return {T} -- The updated array. + @within Array - Updates an array at the given index. If the value at the given index does - not exist, `callback` will be called, and its return value will be used - as the value at the given index. + Updates the value at the given index in the array. If the value at the given index is `nil` or `None`, the `adder` function will be called to add a new value to the array. If the value at the given index is not `nil` or `None`, the `updater` function will be called to update the value at the given index. - ```lua - local array = { 1, 2, 3 } + ```lua + local array = { "a", "b", "c" } - local new = Update(array, 2, function(value) - return value + 1 - end) -- { 2, 3, 3 } + update(array, 2, function(value, index) + return value .. "!" + }) -- { "a", "b!", "c" } - local new = Update(array, 4, function(value) - return value + 1 - end, function(value) - return 10 - end) -- { 1, 2, 3, 10 } - ``` + update(array, 4, nil, function(index) + return "d" + }) -- { "a", "b", "c", "d" } + ``` ]=] local function update( array: { T }, index: number, - updater: Updater?, - callback: Callback? + updater: ((value: T, index: number) -> T)?, + adder: ((index: number) -> T)? ): { T } - local length = #array - local result = Copy(array) + local out = copy(array) + index = Util.normalizeIndex(index, #array) - if index < 1 then - index += length + if updater and out[index] ~= nil and out[index] ~= None then + out[index] = updater(out[index], index) end - updater = if type(updater) == "function" then updater else Util.func.returned - - if result[index] ~= nil then - result[index] = updater(result[index], index) - else - result[index] = call(callback, index) + if adder and (out[index] == nil or out[index] == None) then + out[index] = adder(index) end - return result + return out end return update diff --git a/src/Array/zip.luau b/src/Array/zip.luau index c30f3ec..2ebee7f 100644 --- a/src/Array/zip.luau +++ b/src/Array/zip.luau @@ -1,47 +1,41 @@ ---!strict -local Reduce = require(script.Parent.reduce) +local reduce = require("./reduce") --[=[ - @function zip - @within Array + @within Array - @param ... {any} -- The arrays to zip together. - @return {any} -- The zipped array. + Links together the values of multiple arrays into a single array of arrays, where each index of the new array contains the values of the original arrays at that index. If the arrays are of different lengths, the new array will be the length of the shortest array. - Zips multiple arrays together into a single array. + ```lua + local array1 = { "a", "b", "c", "d" } + local array2 = { 1, 2, 3 } - ```lua - local table1 = { 1, 2, 3 } - local table2 = { "hello", "world", "goodbye" } - - local new = Zip(table1, table2) -- { { 1, "hello" }, { 2, "world" }, { 3, "goodbye" } } - ``` + zip(array1, array2) + -- { { "a", 1 }, { "b", 2 }, { "c", 3 } } + ``` ]=] -local function zip(...: { any }): T - local argCount = select("#", ...) - local arguments = { ... } - - local result = {} - - if argCount == 0 then - return result +local function zip(...: { any }): { { any } } + if select("#", ...) == 0 then + return {} end - local minLength: number = Reduce(arguments, function(acc, val) - return math.min(acc, #val) - end, #arguments[1]) + local arrays = { ... } + local length = reduce(arrays, function(acc, array) + return math.min(acc, #array) + end, math.huge) + + local out = {} - for index = 1, minLength do + for index = 1, length do local values = {} - for _, argArray in ipairs(arguments) do - table.insert(values, argArray[index]) + for _, array in arrays do + table.insert(values, array[index]) end - table.insert(result, values) + table.insert(out, values) end - return result + return out end return zip diff --git a/src/Array/zipAll.luau b/src/Array/zipAll.luau index 33612a2..6050316 100644 --- a/src/Array/zipAll.luau +++ b/src/Array/zipAll.luau @@ -1,51 +1,43 @@ ---!strict -local Sift = script.Parent.Parent - -local Reduce = require(script.Parent.reduce) -local None = require(Sift.None) +local None = require("@Sift/None") +local reduce = require("./reduce") --[=[ - @function zipAll - @within Array - - @param ... ...{any} -- The arrays to zip. - @return {any} -- The zipped array. + @within Array - Zips multiple arrays together into a single array, filling - in missing values with `None`. + Links together the values of multiple arrays into a single array of arrays, where each index of the new array contains the values of the original arrays at that index. If the arrays are of different lengths, the shorter arrays will be padded with `None`. - ```lua - local table1 = { 1, 2, 3, 4 } - local table2 = { "hello", "world", "goodbye" } + ```lua + local array1 = { 1, 2, 3 } + local array2 = { "a", "b", "c", "d" } - local new = ZipAll(table1, table2) -- { { 1, "hello" }, { 2, "world" }, { 3, "goodbye" }, { 4, None } } - ``` + zipAll(array1, array2) + -- { { 1, "a" }, { 2, "b" }, { 3, "c" }, { None, "d" } } + ``` ]=] -local function zipAll(...: { any }): T - local argCount = select("#", ...) - local arguments = { ... } - local result = {} - - if argCount == 0 then - return result +local function zipAll(...: { any }): { { any } } + if select("#", ...) == 0 then + return {} end - local maxLength = Reduce(arguments, function(acc, val) - return math.max(acc, #val) - end, #arguments[1]) + local arrays = { ... } + local length = reduce(arrays, function(acc, array) + return math.max(acc, #array) + end, 0) + + local out = {} - for index = 1, maxLength do + for i = 1, length do local values = {} - for _, argArray in ipairs(arguments) do - local value = argArray[index] - table.insert(values, if value == nil then None else value) + for _, array in arrays do + local value = if array[i] == nil then None else array[i] + table.insert(values, value) end - table.insert(result, values) + table.insert(out, values) end - return result + return out end return zipAll diff --git a/src/Dictionary/copy.luau b/src/Dictionary/copy.luau deleted file mode 100644 index 60c30aa..0000000 --- a/src/Dictionary/copy.luau +++ /dev/null @@ -1,20 +0,0 @@ ---!strict ---[=[ - @function copy - @within Dictionary - - @param dictionary T -- The dictionary to copy. - @return T -- The copied dictionary. - - Copies a dictionary. - - ```lua - local dictionary = { hello = "world" } - - local new = Copy(dictionary) -- { hello = "world" } - - print(new == dictionary) -- false - print(new.hello == dictionary.hello) -- true - ``` -]=] -return table.clone diff --git a/src/Dictionary/copy.luau.todo b/src/Dictionary/copy.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/copyDeep.luau b/src/Dictionary/copyDeep.luau deleted file mode 100644 index 5734f51..0000000 --- a/src/Dictionary/copyDeep.luau +++ /dev/null @@ -1,32 +0,0 @@ ---!strict ---[=[ - @function copyDeep - @within Dictionary - - @param dictionary T -- The dictionary to copy. - @return T -- The copied dictionary. - - Copies a dictionary recursively. - - ```lua - local dictionary = { hello = { world = "goodbye" } } - - local new = CopyDeep(dictionary) -- { hello = { world = "goodbye" } } - - print(new == dictionary) -- false - print(new.hello == dictionary.hello) -- false - ``` -]=] -local function copyDeep(dictionary: T): T - local new = table.clone(dictionary) - - for key, value in pairs(dictionary) do - if type(value) == "table" then - new[key] = copyDeep(value) - end - end - - return new -end - -return copyDeep diff --git a/src/Dictionary/copyDeep.luau.todo b/src/Dictionary/copyDeep.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/count.luau b/src/Dictionary/count.luau deleted file mode 100644 index 0000ef5..0000000 --- a/src/Dictionary/count.luau +++ /dev/null @@ -1,42 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local Util = require(Sift.Util) - ---[=[ - @function count - @within Dictionary - - @param dictionary T -- The dictionary to count. - @param predicate? (value: T, key: K, dictionary: T) -> any -- The predicate to use to filter the dictionary. - @return number -- The number of items in the dictionary. - - Counts the number of items in a dictionary. - - ```lua - local dictionary = { hello = "world", goodbye = "world" } - - local value = Count(dictionary) -- 2 - local value = Count(dictionary, function(item, key) - return item == "world" - end) -- 1 - ``` -]=] -local function count( - dictionary: { [K]: V }, - predicate: ((value: V, key: K, dictionary: { [K]: V }) -> any)? -): number - local counter = 0 - - predicate = if type(predicate) == "function" then predicate else Util.func.truthy - - for key, value in pairs(dictionary) do - if predicate(value, key, dictionary) then - counter += 1 - end - end - - return counter -end - -return count diff --git a/src/Dictionary/count.luau.todo b/src/Dictionary/count.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/entries.luau b/src/Dictionary/entries.luau deleted file mode 100644 index ca8a966..0000000 --- a/src/Dictionary/entries.luau +++ /dev/null @@ -1,27 +0,0 @@ ---!strict ---[=[ - @function entries - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to get the entries from. - @return {{ K, V }} -- The entries in the dictionary. - - Returns the entries in the given dictionary as an array of key-value pairs. - - ```lua - local dictionary = { hello = "roblox", goodbye = "world" } - - local entries = Entries(dictionary) -- { { "hello", "roblox" }, { "goodbye", "world" } } - ``` -]=] -local function entries(dictionary: { [K]: V }): { [number]: { [number]: K | V } } - local result = {} - - for key, value in pairs(dictionary) do - table.insert(result, { key, value }) - end - - return result -end - -return entries diff --git a/src/Dictionary/entries.luau.todo b/src/Dictionary/entries.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/equals.luau b/src/Dictionary/equals.luau deleted file mode 100644 index 7d7e725..0000000 --- a/src/Dictionary/equals.luau +++ /dev/null @@ -1,64 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local Util = require(Sift.Util) -local _T = require(Sift.Types) - -local function compare(a, b) - if type(a) ~= "table" or type(b) ~= "table" then - return a == b - end - - for key, value in pairs(a) do - if b[key] ~= value then - return false - end - end - - for key, value in pairs(b) do - if a[key] ~= value then - return false - end - end - - return true -end - ---[=[ - @function equals - @within Dictionary - - @param ... ...{ [any]: any } -- The dictionaries to compare. - @return boolean -- Whether the dictionaries are equal. - - Compares two dictionaries for equality. - - ```lua - local dictionary = { hello = "world", goodbye = "world" } - local other1 = { hello = "world", goodbye = "world" } - local other2 = { hello = "hello", world = "goodbye" } - - local value = Equals(dictionary, other1) -- true - local value = Equals(dictionary, other1, other2) -- false - ``` -]=] -local function equals(...: _T.AnyDictionary): boolean - if Util.equalObjects(...) then - return true - end - - local totalArgs = select("#", ...) - local firstItem = select(1, ...) - - for i = 2, totalArgs do - local item = select(i, ...) - - if not compare(firstItem, item) then - return false - end - end - - return true -end - -return equals diff --git a/src/Dictionary/equals.luau.todo b/src/Dictionary/equals.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/equalsDeep.luau b/src/Dictionary/equalsDeep.luau deleted file mode 100644 index fba460f..0000000 --- a/src/Dictionary/equalsDeep.luau +++ /dev/null @@ -1,64 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local Util = require(Sift.Util) -local _T = require(Sift.Types) - -local function compareDeep(a, b) - if type(a) ~= "table" or type(b) ~= "table" then - return a == b - end - - for key, value in pairs(a) do - if not compareDeep(value, b[key]) then - return false - end - end - - for key, value in pairs(b) do - if not compareDeep(value, a[key]) then - return false - end - end - - return true -end - ---[=[ - @function equalsDeep - @within Dictionary - - @param ... ...{ [any]: any } -- The dictionaries to compare. - @return boolean -- Whether the dictionaries are equal. - - Compares two dictionaries for equality using deep comparison. - - ```lua - local dictionary = { hello = "world", goodbye = { world = "hello" } } - local other1 = { hello = "world", goodbye = { world = "hello" } } - local other2 = { hello = "hello", world = "goodbye" } - - local value = EqualsDeep(dictionary, other1) -- true - local value = EqualsDeep(dictionary, other1, other2) -- false - ``` -]=] -local function equalsDeep(...: _T.AnyDictionary): boolean - if Util.equalObjects(...) then - return true - end - - local totalArgs = select("#", ...) - local firstItem = select(1, ...) - - for i = 2, totalArgs do - local item = select(i, ...) - - if not compareDeep(firstItem, item) then - return false - end - end - - return true -end - -return equalsDeep diff --git a/src/Dictionary/equalsDeep.luau.todo b/src/Dictionary/equalsDeep.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/every.luau b/src/Dictionary/every.luau deleted file mode 100644 index 03337d0..0000000 --- a/src/Dictionary/every.luau +++ /dev/null @@ -1,37 +0,0 @@ ---!strict ---[=[ - @function every - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to check. - @param predicate (value: V, key: K, dictionary: {[K]: V}) -> any -- The predicate to use to check the dictionary. - @return boolean -- Whether every item in the dictionary passes the predicate. - - Checks whether every item in the dictionary passes the predicate. - - ```lua - local dictionary = { hello = "world", goodbye = "world" } - - local value = Every(dictionary, function(value, key) - return value == "world" - end) -- true - - local value = Every(dictionary, function(value, key) - return value == "hello" - end) -- false - ``` -]=] -local function every( - dictionary: { [K]: V }, - predicate: (value: V, key: K, dictionary: { [K]: V }) -> any -): boolean - for key, value in pairs(dictionary) do - if not predicate(value, key, dictionary) then - return false - end - end - - return true -end - -return every diff --git a/src/Dictionary/every.luau.todo b/src/Dictionary/every.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/filter.luau b/src/Dictionary/filter.luau deleted file mode 100644 index 56f8ff3..0000000 --- a/src/Dictionary/filter.luau +++ /dev/null @@ -1,41 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local Util = require(Sift.Util) - ---[=[ - @function filter - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to filter. - @param predicate? (value: V, key: K, dictionary: {[K]: V}) -> any -- The predicate to use to filter the dictionary. - @return {[K]: V} -- The filtered dictionary. - - Filters a dictionary using a predicate. Any items that do not pass the predicate will be removed from the dictionary. - - ```lua - local dictionary = { hello = "world", goodbye = "goodbye" } - - local result = Filter(dictionary, function(value, key) - return value == "world" - end) -- { hello = "world" } - ``` -]=] -local function filter( - dictionary: { [K]: V }, - predicate: ((value: V, key: K, dictionary: { [K]: V }) -> any)? -): { [K]: V } - local result = {} - - predicate = if type(predicate) == "function" then predicate else Util.func.truthy - - for key, value in pairs(dictionary) do - if predicate(value, key, dictionary) then - result[key] = value - end - end - - return result -end - -return filter diff --git a/src/Dictionary/filter.luau.todo b/src/Dictionary/filter.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/flatten.luau b/src/Dictionary/flatten.luau deleted file mode 100644 index e4c4b00..0000000 --- a/src/Dictionary/flatten.luau +++ /dev/null @@ -1,52 +0,0 @@ ---!strict -local _T = require(script.Parent.Parent.Types) - ---[=[ - @function flatten - @within Dictionary - - @param dictionary T -- The dictionary to flatten. - @param depth? number -- The depth to flatten the dictionary to. - @return T -- The flattened dictionary. - - Flattens a dictionary. If depth is not specified, it will flatten the dictionary as far as it can go. - - ```lua - local dictionary = { - hello = "world", - goodbye = { - world = "hello", - roblox = { - yes = "no", - no = "yes", - } - } - } - - local new = Flatten(dictionary) -- { hello = "world", world = "hello", yes = "no", no = "yes" } - local new = Flatten(dictionary, 1) -- { hello = "world", world = "hello", roblox = { yes = "no", no = "yes" } } - ``` -]=] -local function flatten(dictionary: _T.AnyDictionary, depth: number?): _T.AnyDictionary - depth = if type(depth) == "number" then depth else math.huge - - local result = {} - - for key, value in pairs(dictionary :: _T.AnyDictionary) do - if type(value) == "table" and depth > 0 then - local nested = flatten(value, depth - 1) - - for resultKey, resultValue in pairs(result) do - nested[resultKey] = resultValue - end - - result = nested - else - result[key] = value - end - end - - return result -end - -return flatten diff --git a/src/Dictionary/flatten.luau.todo b/src/Dictionary/flatten.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/flip.luau b/src/Dictionary/flip.luau deleted file mode 100644 index 6af59d1..0000000 --- a/src/Dictionary/flip.luau +++ /dev/null @@ -1,27 +0,0 @@ ---!strict ---[=[ - @function flip - @within Dictionary - - @param dictionary { [K]: V } -- The dictionary to flip. - @return { [V]: K } -- The flipped dictionary. - - Flips a dictionary. Keys become values and values become keys. - - ```lua - local dictionary = { hello = "roblox", goodbye = "world" } - - local new = Flip(dictionary) -- { world = "goodbye", roblox = "hello" } - ``` -]=] -local function flip(dictionary: { [K]: V }): { [V]: K } - local result = {} - - for key, value in pairs(dictionary) do - result[value] = key - end - - return result -end - -return flip diff --git a/src/Dictionary/flip.luau.todo b/src/Dictionary/flip.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/freeze.luau b/src/Dictionary/freeze.luau deleted file mode 100644 index 3f32a46..0000000 --- a/src/Dictionary/freeze.luau +++ /dev/null @@ -1,31 +0,0 @@ ---!strict -local _T = require(script.Parent.Parent.Types) -local Copy = require(script.Parent.copy) - ---[=[ - @function freeze - @within Dictionary - - @param dictionary T -- The dictionary to freeze. - @return T -- The frozen dictionary. - - Freezes the given dictionary at the top level, making it read-only. - - ```lua - local dictionary = { hello = "roblox", goodbye = { world = "world" } } - - local new = Freeze(dictionary) - - new.hello = "world" -- error! - new.goodbye.world = "hello" -- still works! - ``` -]=] -local function freeze(dictionary: _T.AnyDictionary): _T.AnyDictionary - local new = Copy(dictionary) - - table.freeze(new) - - return new -end - -return freeze diff --git a/src/Dictionary/freeze.luau.todo b/src/Dictionary/freeze.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/freezeDeep.luau b/src/Dictionary/freezeDeep.luau deleted file mode 100644 index 4356357..0000000 --- a/src/Dictionary/freezeDeep.luau +++ /dev/null @@ -1,38 +0,0 @@ ---!strict -local _T = require(script.Parent.Parent.Types) - ---[=[ - @function freezeDeep - @within Dictionary - - @param dictionary T -- The dictionary to freeze. - @return T -- The frozen dictionary. - - Freezes the entire dictionary, making it read-only, including all nested dictionaries. - - ```lua - local dictionary = { hello = "roblox", goodbye = { world = "world" } } - - local new = FreezeDeep(dictionary) - - new.hello = "world" -- error! - new.goodbye.world = "hello" -- error! - ``` -]=] -local function freezeDeep(dictionary: _T.AnyDictionary): _T.AnyDictionary - local result = {} - - for key, value in pairs(dictionary) do - if type(value) == "table" then - result[key] = freezeDeep(value) - else - result[key] = value - end - end - - table.freeze(result) - - return result -end - -return freezeDeep diff --git a/src/Dictionary/freezeDeep.luau.todo b/src/Dictionary/freezeDeep.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/fromArrays.luau b/src/Dictionary/fromArrays.luau deleted file mode 100644 index ed6e99d..0000000 --- a/src/Dictionary/fromArrays.luau +++ /dev/null @@ -1,31 +0,0 @@ ---!strict ---[=[ - @function fromArrays - @within Dictionary - - @param keys {K} -- An array containing values to be used as keys. - @param values {V} -- An array containing values to be used as values. - @return {[K]: V} -- A dictionary composed of the given keys and values. - - Creates a dictionary from the given arrays, where the first array is used - as keys and the second array is used as values. - - ```lua - local keys = { "hello", "goodbye" } - local values = { "roblox", "world" } - - local dictionary = FromArrays(keys, values) -- { hello = "roblox", goodbye = "world" } - ``` -]=] -local function fromArrays(keys: { K }, values: { V }): { [K]: V } - local keysLength = #keys - local result = {} - - for i = 1, keysLength do - result[keys[i]] = values[i] - end - - return result -end - -return fromArrays diff --git a/src/Dictionary/fromArrays.luau.todo b/src/Dictionary/fromArrays.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/fromEntries.luau b/src/Dictionary/fromEntries.luau deleted file mode 100644 index 7ae818a..0000000 --- a/src/Dictionary/fromEntries.luau +++ /dev/null @@ -1,27 +0,0 @@ ---!strict ---[=[ - @function fromEntries - @within Dictionary - - @param entries {{ K, V }} -- An array of key-value pairs. - @return {[K]: V} -- A dictionary composed of the given key-value pairs. - - Creates a dictionary from the given key-value pairs. - - ```lua - local entries = { { "hello", "roblox" }, { "goodbye", "world" } } - - local dictionary = FromEntries(entries) -- { hello = "roblox", goodbye = "world" } - ``` -]=] -local function fromEntries(entries: { [number]: { [number]: K | V } }): { [K]: V } - local result = {} - - for _, entry in ipairs(entries) do - result[entry[1]] = entry[2] - end - - return result -end - -return fromEntries diff --git a/src/Dictionary/fromEntries.luau.todo b/src/Dictionary/fromEntries.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/has.luau b/src/Dictionary/has.luau deleted file mode 100644 index 97e9952..0000000 --- a/src/Dictionary/has.luau +++ /dev/null @@ -1,25 +0,0 @@ ---!strict -local _T = require(script.Parent.Parent.Types) - ---[=[ - @function has - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to check. - @param key any -- The key to check for. - @return boolean -- Whether or not the dictionary has the given key. - - Checks whether or not the given dictionary has the given key. - - ```lua - local dictionary = { hello = "roblox", goodbye = "world" } - - local hasHello = Has(dictionary, "hello") -- true - local hasCat = Has(dictionary, "cat") -- false - ``` -]=] -local function has(dictionary: _T.AnyDictionary, key: any): boolean - return dictionary[key] ~= nil -end - -return has diff --git a/src/Dictionary/has.luau.todo b/src/Dictionary/has.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/includes.luau b/src/Dictionary/includes.luau deleted file mode 100644 index 3106cd4..0000000 --- a/src/Dictionary/includes.luau +++ /dev/null @@ -1,29 +0,0 @@ ---!strict ---[=[ - @function includes - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to check. - @param value V -- The value to check for. - @return boolean -- Whether or not the dictionary includes the given value. - - Checks whether or not the given dictionary includes the given value. - - ```lua - local dictionary = { hello = "roblox", goodbye = "world" } - - local includesRoblox = Includes(dictionary, "roblox") -- true - local includesCat = Includes(dictionary, "cat") -- false - ``` -]=] -local function includes(dictionary: { [K]: V }, value: V): boolean - for _, v in pairs(dictionary) do - if v == value then - return true - end - end - - return false -end - -return includes diff --git a/src/Dictionary/includes.luau.todo b/src/Dictionary/includes.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/init.luau b/src/Dictionary/init.luau index f68e6eb..85ae286 100644 --- a/src/Dictionary/init.luau +++ b/src/Dictionary/init.luau @@ -1,51 +1,4 @@ ---!strict --[=[ - @class Dictionary - - Dictionaries are a type of data structure that can be used to store key-value pairs. - - ```lua - local dictionary = { - cats = 2, - dogs = 1 - } - - print(dictionary.cats) -- 2 - ``` + @class Dictionary ]=] -local Dictionary = { - copy = require(script.copy), - copyDeep = require(script.copyDeep), - count = require(script.count), - entries = require(script.entries), - equals = require(script.equals), - equalsDeep = require(script.equalsDeep), - every = require(script.every), - filter = require(script.filter), - flatten = require(script.flatten), - flip = require(script.flip), - freeze = require(script.freeze), - freezeDeep = require(script.freezeDeep), - fromArrays = require(script.fromArrays), - fromEntries = require(script.fromEntries), - has = require(script.has), - includes = require(script.includes), - keys = require(script.keys), - map = require(script.map), - merge = require(script.merge), - mergeDeep = require(script.mergeDeep), - removeKey = require(script.removeKey), - removeKeys = require(script.removeKeys), - removeValue = require(script.removeValue), - removeValues = require(script.removeValues), - set = require(script.set), - some = require(script.some), - update = require(script.update), - values = require(script.values), - withKeys = require(script.withKeys), -} - -Dictionary.join = Dictionary.merge -Dictionary.joinDeep = Dictionary.mergeDeep - -return Dictionary +return {} diff --git a/src/Dictionary/keys.luau b/src/Dictionary/keys.luau deleted file mode 100644 index 40fe565..0000000 --- a/src/Dictionary/keys.luau +++ /dev/null @@ -1,27 +0,0 @@ ---!strict ---[=[ - @function keys - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to get the keys of. - @return {K} -- An array containing the keys of the given dictionary. - - Gets the keys of the given dictionary as an array. - - ```lua - local dictionary = { hello = "roblox", goodbye = "world" } - - local keys = Keys(dictionary) -- { "hello", "goodbye" } - ``` -]=] -local function keys(dictionary: { [K]: V }): { K } - local result = {} - - for key in pairs(dictionary) do - table.insert(result, key) - end - - return result -end - -return keys diff --git a/src/Dictionary/keys.luau.todo b/src/Dictionary/keys.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/map.luau b/src/Dictionary/map.luau deleted file mode 100644 index f878da3..0000000 --- a/src/Dictionary/map.luau +++ /dev/null @@ -1,40 +0,0 @@ ---!strict ---[=[ - @function map - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to map. - @param mapper (value: V, key: K, dictionary: {[K]: V}) -> (Y?, X?) -- The mapper function. - @return {[X]: Y} -- The mapped dictionary. - - Maps the dictionary using the mapper function. The mapper function can - return a value and a key. If the mapper function does not return a key, - the original key will be used. - - ```lua - local dictionary = { hello = 10, goodbye = 20 } - - local new = Map(dictionary, function(value, key) - return value * 2, key .. "!" - end) -- { ["hello!"] = 20, ["goodbye!"] = 40 } - - local new = Map(dictionary, function(value, key) - return value * 10 - end) -- { hello = 100, goodbye = 200 } - ``` -]=] -local function map( - dictionary: { [K]: V }, - mapper: (value: V, key: K, dictionary: { [K]: V }) -> (Y?, X?) -): { [X]: Y } - local mapped = {} - - for key, value in pairs(dictionary) do - local mappedValue, mappedKey = mapper(value, key, dictionary) - mapped[mappedKey or key] = mappedValue - end - - return mapped -end - -return map diff --git a/src/Dictionary/map.luau.todo b/src/Dictionary/map.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/merge.luau b/src/Dictionary/merge.luau deleted file mode 100644 index f02804d..0000000 --- a/src/Dictionary/merge.luau +++ /dev/null @@ -1,45 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local None = require(Sift.None) - ---[=[ - @function merge - @within Dictionary - - @param dictionaries? ...any -- The dictionaries to merge. - @return T -- The merged dictionary. - - Merges the given dictionaries into a single dictionary. If the - value is `None`, it will be removed from the result. The - parameters may be any number of dictionaries or `nil`. - Non-dictonaries will be ignored. - - Aliases: `join` - - ```lua - local dictionary1 = { hello = "roblox", goodbye = "world" } - local dictionary2 = { goodbye = "goodbye" } - - local merged = Merge(dictionary1, dictionary2) -- { hello = "roblox", goodbye = "goodbye" } - ``` -]=] -local function merge(...: any): T - local result = {} - - for dictionaryIndex = 1, select("#", ...) do - local dictionary = select(dictionaryIndex, ...) - - if type(dictionary) ~= "table" then - continue - end - - for key, value in pairs(dictionary) do - result[key] = if value == None then nil else value - end - end - - return result -end - -return merge diff --git a/src/Dictionary/merge.luau.todo b/src/Dictionary/merge.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/mergeDeep.luau b/src/Dictionary/mergeDeep.luau deleted file mode 100644 index e0ba505..0000000 --- a/src/Dictionary/mergeDeep.luau +++ /dev/null @@ -1,56 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local None = require(Sift.None) -local copyDeep = require(script.Parent.copyDeep) - ---[=[ - @function mergeDeep - @within Dictionary - - @param dictionaries? ...any -- The dictionaries to merge. - @return T -- The merged dictionary. - - Merges the given dictionaries into a single dictionary. If the - value is `None`, it will be removed from the result. This is - recursive. The parameters may be any number of dictionaries or - `nil`. Non-dictonaries will be ignored. - - Aliases: `joinDeep` - - ```lua - local dictionary1 = { hello = "roblox", goodbye = { world = "goodbye" } } - local dictionary2 = { goodbye = { world = "world" } } - - local merged = MergeDeep(dictionary1, dictionary2) -- { hello = "roblox", goodbye = { world = "world" } } - ``` -]=] -local function mergeDeep(...: any): T - local result = {} - - for dictionaryIndex = 1, select("#", ...) do - local dictionary = select(dictionaryIndex, ...) - - if type(dictionary) ~= "table" then - continue - end - - for key, value in pairs(dictionary) do - if value == None then - result[key] = nil - elseif type(value) == "table" then - if result[key] == nil or type(result[key]) ~= "table" then - result[key] = copyDeep(value) - else - result[key] = mergeDeep(result[key], value) - end - else - result[key] = value - end - end - end - - return result -end - -return mergeDeep diff --git a/src/Dictionary/mergeDeep.luau.todo b/src/Dictionary/mergeDeep.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/removeKey.luau b/src/Dictionary/removeKey.luau deleted file mode 100644 index 6659fac..0000000 --- a/src/Dictionary/removeKey.luau +++ /dev/null @@ -1,29 +0,0 @@ ---!strict -local copy = require(script.Parent.copy) - ---[=[ - @function removeKey - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to remove the key from. - @param key K -- The key to remove. - @return {[K]: V} -- The dictionary without the given key. - - Removes the given key from the given dictionary. - - ```lua - local dictionary = { hello = "roblox", goodbye = "world" } - - local withoutHello = RemoveKey(dictionary, "hello") -- { goodbye = "world" } - local withoutGoodbye = RemoveKey(dictionary, "goodbye") -- { hello = "roblox" } - ``` -]=] -local function removeKey(dictionary: { [K]: V }, key: K): { [K]: V } - local result = copy(dictionary) - - result[key] = nil - - return result -end - -return removeKey diff --git a/src/Dictionary/removeKey.luau.todo b/src/Dictionary/removeKey.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/removeKeys.luau b/src/Dictionary/removeKeys.luau deleted file mode 100644 index 93ff109..0000000 --- a/src/Dictionary/removeKeys.luau +++ /dev/null @@ -1,30 +0,0 @@ ---!strict -local copy = require(script.Parent.copy) - ---[=[ - @function removeKeys - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to remove the keys from. - @param keys ...K -- The keys to remove. - @return {[K]: V} -- The dictionary without the given keys. - - Removes the given keys from the given dictionary. - - ```lua - local dictionary = { hello = "world", cat = "meow", dog = "woof", unicorn = "rainbow" } - - local withoutCatDog = RemoveKeys(dictionary, "cat", "dog") -- { hello = "world", unicorn = "rainbow" } - ``` -]=] -local function removeKeys(dictionary: { [K]: V }, ...: K): { [K]: V } - local result = copy(dictionary) - - for _, key in ipairs({ ... }) do - result[key] = nil - end - - return result -end - -return removeKeys diff --git a/src/Dictionary/removeKeys.luau.todo b/src/Dictionary/removeKeys.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/removeValue.luau b/src/Dictionary/removeValue.luau deleted file mode 100644 index e8280a8..0000000 --- a/src/Dictionary/removeValue.luau +++ /dev/null @@ -1,31 +0,0 @@ ---!strict ---[=[ - @function removeValue - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to remove the value from. - @param value V -- The value to remove. - @return {[K]: V} -- The dictionary without the given value. - - Removes the given value from the given dictionary. - - ```lua - local dictionary = { hello = "roblox", goodbye = "world" } - - local withoutHello = RemoveValue(dictionary, "roblox") -- { goodbye = "world" } - local withoutGoodbye = RemoveValue(dictionary, "world") -- { hello = "roblox" } - ``` -]=] -local function removeValue(dictionary: { [K]: V }, value: V): { [K]: V } - local result = {} - - for key, v in pairs(dictionary) do - if v ~= value then - result[key] = v - end - end - - return result -end - -return removeValue diff --git a/src/Dictionary/removeValue.luau.todo b/src/Dictionary/removeValue.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/removeValues.luau b/src/Dictionary/removeValues.luau deleted file mode 100644 index 0ece520..0000000 --- a/src/Dictionary/removeValues.luau +++ /dev/null @@ -1,36 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local ToSet = require(Sift.Array.toSet) - ---[=[ - @function removeValues - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to remove the values from. - @param values ...V -- The values to remove. - @return {[K]: V} -- The dictionary without the given values. - - Removes the given values from the given dictionary. - - ```lua - local dictionary = { hello = "world", cat = "meow", unicorn = "rainbow", goodbye = "world" } - - local withoutWorld = RemoveValues(dictionary, "world") -- { cat = "meow", unicorn = "rainbow" } - local onlyWorld = RemoveValues(dictionary, "meow", "rainbow") -- { hello = "world", goodbye = "world" } - ``` -]=] -local function removeValues(dictionary: { [K]: V }, ...: V): { [K]: V } - local values = ToSet({ ... }) - local result = {} - - for key, value in pairs(dictionary) do - if not values[value] then - result[key] = value - end - end - - return result -end - -return removeValues diff --git a/src/Dictionary/removeValues.luau.todo b/src/Dictionary/removeValues.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/set.luau b/src/Dictionary/set.luau deleted file mode 100644 index 9cd2d5e..0000000 --- a/src/Dictionary/set.luau +++ /dev/null @@ -1,29 +0,0 @@ ---!strict -local copy = require(script.Parent.copy) - ---[=[ - @function set - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to set the value in. - @param key K -- The key to set the value in. - @param value V -- The value to set. - @return {[K]: V} -- The dictionary with the given value set. - - Sets the given value in the given dictionary. - - ```lua - local dictionary = { hello = "world", cat = "meow", unicorn = "rainbow" } - - local setCat = Set(dictionary, "cat", "woof") -- { hello = "world", cat = "woof", unicorn = "rainbow" } - ``` -]=] -local function set(dictionary: { [K]: V }, key: K, value: V): { [K]: V } - local result = copy(dictionary) - - result[key] = value - - return result -end - -return set diff --git a/src/Dictionary/set.luau.todo b/src/Dictionary/set.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/some.luau b/src/Dictionary/some.luau deleted file mode 100644 index af416be..0000000 --- a/src/Dictionary/some.luau +++ /dev/null @@ -1,37 +0,0 @@ ---!strict ---[=[ - @function some - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to check. - @param predicate (value: V, key: K, dictionary: { [K]: V }) -> any -- The predicate to check against. - @return boolean -- Whether or not the predicate returned true for any value. - - Checks whether or not the predicate returned true for any value in the dictionary. - - ```lua - local dictionary = { hello = "world", cat = "meow", unicorn = "rainbow" } - - local hasMeow = Some(dictionary, function(value) - return value == "meow" - end) -- true - - local hasDog = Some(dictionary, function(_, key) - return key == "dog" - end) -- false - ``` -]=] -local function some( - dictionary: { [K]: V }, - predicate: (value: V, key: V, dictionary: { [K]: V }) -> any -): boolean - for key, value in pairs(dictionary) do - if predicate(value, key, dictionary) then - return true - end - end - - return false -end - -return some diff --git a/src/Dictionary/some.luau.todo b/src/Dictionary/some.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/update.luau b/src/Dictionary/update.luau deleted file mode 100644 index 4a5ff6b..0000000 --- a/src/Dictionary/update.luau +++ /dev/null @@ -1,60 +0,0 @@ ---!strict -local copy = require(script.Parent.copy) - -type Callback = (key: K) -> V -type Updater = (value: V, key: K) -> V - -local function call(callback: Callback, key: K) - if type(callback) == "function" then - return callback(key) - end -end - ---[=[ - @function update - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to update. - @param key K -- The key to update. - @param updater? (value: V, key: K) -> U -- The updater function. - @param callback? (key: K) -> C -- The callback function. - @return {[K]: V & U & C } -- The updated dictionary. - - Updates a value in a dictionary at the given key. If the value at the given key does not exist, `callback` will be called, and its return value will be used as the value at the given key. - - ```lua - local dictionary = { cats = 2 } - - local new = Update(dictionary, "cats", function(value) - return value + 1 - end) -- { cats = 3 } - - local new = Update(dictionary, "dogs", function(value) - return value + 1 - end, function(value) - return 1 - end) -- { cats = 3, dogs = 1 } - ``` -]=] -local function update( - dictionary: { [K]: V }, - key: K, - updater: ((value: V, key: K) -> U)?, - callback: ((key: K) -> C)? -): { [K]: V & U & C } - local result = copy(dictionary) - - if result[key] ~= nil then - if updater then - result[key] = updater(result[key], key) - end - else - if callback then - result[key] = call(callback, key) - end - end - - return result -end - -return update diff --git a/src/Dictionary/update.luau.todo b/src/Dictionary/update.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/values.luau b/src/Dictionary/values.luau deleted file mode 100644 index 6db73b3..0000000 --- a/src/Dictionary/values.luau +++ /dev/null @@ -1,27 +0,0 @@ ---!strict ---[=[ - @function values - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to get the values from. - @return {V} -- The values in the dictionary. - - Gets the values in the given dictionary. - - ```lua - local dictionary = { hello = "roblox", goodbye = "world" } - - local values = Values(dictionary) -- { "roblox", "world" } - ``` -]=] -local function values(dictionary: { [K]: V }): { V } - local result = {} - - for _, value in pairs(dictionary) do - table.insert(result, value) - end - - return result -end - -return values diff --git a/src/Dictionary/values.luau.todo b/src/Dictionary/values.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Dictionary/withKeys.luau b/src/Dictionary/withKeys.luau deleted file mode 100644 index d69ed43..0000000 --- a/src/Dictionary/withKeys.luau +++ /dev/null @@ -1,29 +0,0 @@ ---!strict - ---[=[ - @function withKeys - @within Dictionary - - @param dictionary {[K]: V} -- The dictionary to select the keys from. - @param keys ...K -- The keys to keep. - @return {[K]: V} -- The dictionary with only the given keys. - - Returns a dictionary with the given keys. - - ```lua - local dictionary = { hello = "world", cat = "meow", dog = "woof", unicorn = "rainbow" } - - local withoutCatDog = WithKeys(dictionary, "cat", "dog") -- { cat = "meow", dog = "woof" } - ``` -]=] -local function withKeys(dictionary: { [K]: V }, ...: K): { [K]: V } - local result = {} - - for _, key in ipairs({ ... }) do - result[key] = dictionary[key] - end - - return result -end - -return withKeys diff --git a/src/Dictionary/withKeys.luau.todo b/src/Dictionary/withKeys.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/None.luau b/src/None.luau index 35621e7..15d886e 100644 --- a/src/None.luau +++ b/src/None.luau @@ -1,16 +1,20 @@ ---!strict --[=[ - @prop None None @within Sift + @prop None None - Luau can't distinguish between a nil value and a non-existent value. This - constant is used to represent a non-existent value. It can be used in methods - like `Array.Concat` or `Dictionary.Merge` to remove the value from the result. + Luau doesn't have a built-in `undefined` type, so Sift provides a `None` value to represent the absence of a value. + + ```lua + merge({ foo = "bar", baz = "qux" }, { foo = Sift.None }) + -- { baz = "qux" } + ``` ]=] -local None = newproxy(true) +local None: unknown = newproxy(true) getmetatable(None :: any).__tostring = function() return "Sift.None" end +export type None = typeof(None) + return None diff --git a/src/Set/add.luau b/src/Set/add.luau deleted file mode 100644 index e388d54..0000000 --- a/src/Set/add.luau +++ /dev/null @@ -1,32 +0,0 @@ ---!strict ---[=[ - @function add - @within Set - - @param set { [T]: boolean } -- The set to add the value to. - @param ... ...T -- The values to add. - @return { [T]: boolean } -- The set with the values added. - - Adds values to a set. - - ```lua - local set = { hello = true } - - local newSet = Add(set, "world") -- { hello = true, world = true } - ``` -]=] -local function add(set: { [T]: boolean }, ...: T): { [T]: boolean } - local result = {} - - for key, _ in pairs(set) do - result[key] = true - end - - for _, value in ipairs({ ... }) do - result[value] = true - end - - return result -end - -return add diff --git a/src/Set/add.luau.todo b/src/Set/add.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/copy.luau b/src/Set/copy.luau deleted file mode 100644 index c074e8c..0000000 --- a/src/Set/copy.luau +++ /dev/null @@ -1,21 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local copy = require(Sift.Dictionary.copy) - ---[=[ - @function copy - @within Set - - @param set { [T]: boolean } -- The set to copy. - @return { [T]: boolean } -- A copy of the set. - - Creates a copy of a set. - - ```lua - local set = { hello = true } - - local newSet = Copy(set) -- { hello = true } - ``` -]=] -return copy diff --git a/src/Set/copy.luau.todo b/src/Set/copy.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/count.luau b/src/Set/count.luau deleted file mode 100644 index 2608fae..0000000 --- a/src/Set/count.luau +++ /dev/null @@ -1,42 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local Util = require(Sift.Util) - ---[=[ - @function count - @within Set - - @param set { [T]: boolean } -- The set to count. - @param predicate? (item: T, set: { [T]: boolean }) -> boolean? -- The predicate to use to count. - @return number -- The number of items in the set. - - Counts the number of items in a set. - - ```lua - local set = { hello = true, world = true } - - local count = Count(set) -- 2 - local count = Count(set, function(item) - return item == "hello" - end) -- 1 - ``` -]=] -local function count( - set: { [T]: boolean }, - predicate: ((item: T, set: { [T]: boolean }) -> boolean?)? -): number - local counter = 0 - - predicate = if type(predicate) == "function" then predicate else Util.func.truthy - - for item, _ in pairs(set) do - if predicate(item, set) then - counter += 1 - end - end - - return counter -end - -return count diff --git a/src/Set/count.luau.todo b/src/Set/count.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/delete.luau b/src/Set/delete.luau deleted file mode 100644 index 27086bc..0000000 --- a/src/Set/delete.luau +++ /dev/null @@ -1,34 +0,0 @@ ---!strict ---[=[ - @function delete - @within Set - - @param set { [T]: boolean } -- The set to delete from. - @param ... ...T -- The values to delete. - @return { [T]: boolean } -- The set with the values deleted. - - Deletes values from a set. - - Aliases: `subtract` - - ```lua - local set = { hello = true, world = true } - - local newSet = Delete(set, "hello") -- { world = true } - ``` -]=] -local function delete(set: { [T]: boolean }, ...: T): { [T]: boolean } - local result = {} - - for key, _ in pairs(set) do - result[key] = true - end - - for _, value in ipairs({ ... }) do - result[value] = nil - end - - return result -end - -return delete diff --git a/src/Set/delete.luau.todo b/src/Set/delete.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/difference.luau b/src/Set/difference.luau deleted file mode 100644 index 981306c..0000000 --- a/src/Set/difference.luau +++ /dev/null @@ -1,37 +0,0 @@ ---!strict -local T = require(script.Parent.Parent.Types) - ---[=[ - @function difference - @within Set - - @param set Set -- The set to compare. - @param ... ...Set -- The sets to compare against. - @return Set -- The difference between the sets. - - Returns a set of values that are in the first set, but not in the other sets. - - ```lua - local set1 = { hello = true, world = true } - local set2 = { cat = true, dog = true, hello = true } - - local difference = Difference(set1, set2) -- { world = true } - ``` -]=] -local function difference(set: T.Set, ...: T.Set): T.Set - local diff = table.clone(set) - - for _, nextSet in { ... } do - if typeof(nextSet) ~= "table" then - continue - end - - for value in nextSet do - diff[value] = nil - end - end - - return diff -end - -return difference diff --git a/src/Set/difference.luau.todo b/src/Set/difference.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/differenceSymmetric.luau b/src/Set/differenceSymmetric.luau deleted file mode 100644 index 0b25d29..0000000 --- a/src/Set/differenceSymmetric.luau +++ /dev/null @@ -1,41 +0,0 @@ ---!strict -local T = require(script.Parent.Parent.Types) - ---[=[ - @function differenceSymmetric - @within Set - - @param set Set -- The set to compare. - @param ... ...Set -- The sets to compare against. - @return Set -- The symmetric difference between the sets. - - Returns a set of values that are in the first set, but not in the other sets, and vice versa. - - ```lua - local set1 = { hello = true, world = true } - local set2 = { cat = true, dog = true, hello = true } - - local differenceSymmetric = DifferenceSymmetric(set1, set2) -- { world = true, cat = true, dog = true } - ``` -]=] -local function differenceSymmetric(set: T.Set, ...: T.Set): T.Set - local diff = table.clone(set) - - for _, nextSet in { ... } do - if typeof(nextSet) ~= "table" then - continue - end - - for value in nextSet do - diff[value] = if diff[value] == nil then true else false - end - end - - for value, keep in diff do - diff[value] = if keep then true else nil - end - - return diff -end - -return differenceSymmetric diff --git a/src/Set/differenceSymmetric.luau.todo b/src/Set/differenceSymmetric.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/filter.luau b/src/Set/filter.luau deleted file mode 100644 index cf7d5e2..0000000 --- a/src/Set/filter.luau +++ /dev/null @@ -1,41 +0,0 @@ ---!strict -local Sift = script.Parent.Parent - -local Util = require(Sift.Util) - ---[=[ - @function filter - @within Set - - @param set { [T]: boolean } -- The set to filter. - @param predicate? (item: T, set: { [T]: boolean }) -> any -- The function to filter the set with. - @return { [T]: boolean } -- The filtered set. - - Filters a set using a predicate. Any items that do not pass the predicate will be removed from the set. - - ```lua - local set = { hello = true, world = true } - - local newSet = Filter(set, function(value) - return value ~= "hello" - end) -- { world = true } - ``` -]=] -local function filter( - set: { [T]: boolean }, - predicate: ((T, { [T]: boolean }) -> any)? -): { [T]: boolean } - local result = {} - - predicate = if type(predicate) == "function" then predicate else Util.func.truthy - - for key, _ in pairs(set) do - if predicate(key, set) then - result[key] = true - end - end - - return result -end - -return filter diff --git a/src/Set/filter.luau.todo b/src/Set/filter.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/fromArray.luau b/src/Set/fromArray.luau deleted file mode 100644 index 2603e2d..0000000 --- a/src/Set/fromArray.luau +++ /dev/null @@ -1,30 +0,0 @@ ---!strict ---[=[ - @function fromArray - @within Set - - @param array {T} -- The array to convert to a set. - @return {[T]: boolean} -- The set. - - Converts an array to a set, where each item is mapped to true. - Duplicate items are discarded. - - Aliases: `fromList` - - ```lua - local array = { "hello", "world", "hello" } - - local set = FromArray(array) -- { hello = true, world = true } - ``` -]=] -local function fromArray(array: { T }): { [T]: boolean } - local result = table.create(#array) - - for _, value in ipairs(array) do - result[value] = true - end - - return result -end - -return fromArray diff --git a/src/Set/fromArray.luau.todo b/src/Set/fromArray.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/has.luau b/src/Set/has.luau deleted file mode 100644 index 60a9ffc..0000000 --- a/src/Set/has.luau +++ /dev/null @@ -1,22 +0,0 @@ ---!strict ---[=[ - @function has - @within Set - - @param set { [T]: boolean } -- The set to check. - @param value any -- The value to check for. - @return boolean -- Whether the value is in the set. - - Checks whether a value is in a set. - - ```lua - local set = { hello = true } - - local has = Has(set, "hello") -- true - ``` -]=] -local function has(set: { [T]: boolean }, value: any): boolean - return set[value] == true -end - -return has diff --git a/src/Set/has.luau.todo b/src/Set/has.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/init.luau b/src/Set/init.luau index a3290e8..1435ca7 100644 --- a/src/Set/init.luau +++ b/src/Set/init.luau @@ -1,38 +1,4 @@ ---!strict --[=[ - @class Set - - Sets are a collection of values. They are used to store unique values. - They are essentially a dictionary, but each value is stored as a boolean. - This means that a value can only be in a set once. - - ```lua - local set = { hello = true } - - local newSet = Add(set, "world") -- { hello = true, world = true } - ``` + @class Set ]=] -local set = { - add = require(script.add), - copy = require(script.copy), - count = require(script.count), - delete = require(script.delete), - difference = require(script.difference), - differenceSymmetric = require(script.differenceSymmetric), - filter = require(script.filter), - fromArray = require(script.fromArray), - has = require(script.has), - intersection = require(script.intersection), - isSubset = require(script.isSubset), - isSuperset = require(script.isSuperset), - map = require(script.map), - merge = require(script.merge), - toArray = require(script.toArray), -} - -set.fromList = set.fromArray -set.join = set.merge -set.subtract = set.delete -set.union = set.merge - -return set +return {} diff --git a/src/Set/intersection.luau b/src/Set/intersection.luau deleted file mode 100644 index 5ad9dd9..0000000 --- a/src/Set/intersection.luau +++ /dev/null @@ -1,46 +0,0 @@ ---!strict ---[=[ - @function intersection - @within Set - - @param ... ...{ [any]: boolean } -- The sets to intersect. - @return { [T]: boolean } -- The intersection of the sets. - - Creates the intersection of multiple sets. The intersection - is when both sets have a value in common. Unmatched values - are discarded. - - ```lua - local set1 = { hello = true, world = true } - local set2 = { world = true, universe = true } - - local intersection = Intersection(set1, set2) -- { world = true } - ``` -]=] -local function intersection(...: { [any]: boolean }): { [T]: boolean } - local setCount = select("#", ...) - local firstSet = select(1, ...) - - local result = {} - - for key, _ in pairs(firstSet) do - local intersects = true - - for index = 2, setCount do - local set = select(index, ...) - - if set[key] ~= true then - intersects = false - break - end - end - - if intersects then - result[key] = true - end - end - - return result -end - -return intersection diff --git a/src/Set/intersection.luau.todo b/src/Set/intersection.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/isSubset.luau b/src/Set/isSubset.luau deleted file mode 100644 index bc6d554..0000000 --- a/src/Set/isSubset.luau +++ /dev/null @@ -1,29 +0,0 @@ ---!strict ---[=[ - @function isSubset - @within Set - - @param subset { [any]: boolean } -- The subset to check. - @param superset { [any]: boolean } -- The superset to check against. - @return boolean -- Whether the subset is a subset of the superset. - - Checks whether a set is a subset of another set. - - ```lua - local set = { hello = true, world = true } - local subset = { hello = true } - - local isSubset = IsSubset(subset, set) -- true - ``` -]=] -local function isSubset(subset: { [any]: boolean }, superset: { [any]: boolean }): boolean - for key, value in pairs(subset) do - if superset[key] ~= value then - return false - end - end - - return true -end - -return isSubset diff --git a/src/Set/isSubset.luau.todo b/src/Set/isSubset.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/isSuperset.luau b/src/Set/isSuperset.luau deleted file mode 100644 index 20fd656..0000000 --- a/src/Set/isSuperset.luau +++ /dev/null @@ -1,25 +0,0 @@ ---!strict -local isSubset = require(script.Parent.isSubset) - ---[=[ - @function isSuperset - @within Set - - @param superset { [any]: boolean } -- The superset to check. - @param subset { [any]: boolean } -- The subset to check against. - @return boolean -- Whether the superset is a superset of the subset. - - Checks whether a set is a superset of another set. - - ```lua - local set = { hello = true, world = true } - local subset = { hello = true } - - local isSuperset = IsSuperset(set, subset) -- true - ``` -]=] -local function isSuperset(superset: { [any]: boolean }, subset: { [any]: boolean }): boolean - return isSubset(subset, superset) -end - -return isSuperset diff --git a/src/Set/isSuperset.luau.todo b/src/Set/isSuperset.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/map.luau b/src/Set/map.luau deleted file mode 100644 index 98d7ef9..0000000 --- a/src/Set/map.luau +++ /dev/null @@ -1,34 +0,0 @@ ---!strict ---[=[ - @function map - @within Set - - @param set { [T]: boolean } -- The set to map. - @param mapper (T, {[T]: boolean}) -> U -- The mapper function. - @return {[U]: boolean} -- The mapped set. - - Iterates over a set, calling a mapper function for each item. - - ```lua - local set = { hello = true, world = true } - - local mappedSet = Map(set, function(value) - return value .. "!" - end) -- { ["hello!"] = true, ["world!"] = true } - ``` -]=] -local function map(set: { [T]: boolean }, mapper: (T, { [T]: boolean }) -> U): { [U]: boolean } - local result = {} - - for key, _ in pairs(set) do - local mappedKey = mapper(key, set) - - if mappedKey ~= nil then - result[mappedKey] = true - end - end - - return result -end - -return map diff --git a/src/Set/map.luau.todo b/src/Set/map.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/merge.luau b/src/Set/merge.luau deleted file mode 100644 index 2206eb9..0000000 --- a/src/Set/merge.luau +++ /dev/null @@ -1,38 +0,0 @@ ---!strict ---[=[ - @function merge - @within Set - - @param ... ...any -- The sets to merge. - @return { [T]: boolean } -- The merged set. - - Combines one or more sets into a single set. - - Aliases: `join`, `union` - - ```lua - local set1 = { hello = true, world = true } - local set2 = { cat = true, dog = true, hello = true } - - local merge = Merge(set1, set2) -- { hello = true, world = true, cat = true, dog = true } - ``` -]=] -local function merge(...: any): { [T]: boolean } - local result = {} - - for setIndex = 1, select("#", ...) do - local set = select(setIndex, ...) - - if type(set) ~= "table" then - continue - end - - for key, _ in pairs(set) do - result[key] = true - end - end - - return result -end - -return merge diff --git a/src/Set/merge.luau.todo b/src/Set/merge.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Set/toArray.luau b/src/Set/toArray.luau deleted file mode 100644 index 47af022..0000000 --- a/src/Set/toArray.luau +++ /dev/null @@ -1,27 +0,0 @@ ---!strict ---[=[ - @function toArray - @within Set - - @param set { [T]: boolean } -- The set to convert to an array. - @return {T} -- The array. - - Converts a set to an array. - - ```lua - local set = { hello = true, world = true } - - local array = ToArray(set) -- { "hello", "world" } - ``` -]=] -local function toArray(set: { [T]: boolean }): { T } - local result = {} - - for key, _ in pairs(set) do - table.insert(result, key) - end - - return result -end - -return toArray diff --git a/src/Set/toArray.luau.todo b/src/Set/toArray.luau.todo new file mode 100644 index 0000000..e69de29 diff --git a/src/Types.luau b/src/Types.luau index 6888931..4eb43dd 100644 --- a/src/Types.luau +++ b/src/Types.luau @@ -1,16 +1,13 @@ --selene: allow(unused_variable) -local None = require(script.Parent.None) +local None = require("./Types") --[=[ @type None None @within Sift ]=] export type None = typeof(None) -export type Dictionary = { [K]: V } -export type Array = Dictionary -export type Set = Dictionary -export type Table = Dictionary +export type Dictionary = { [K]: V } +export type Array = Dictionary +export type Set = Dictionary -export type AnyDictionary = Dictionary - -return nil +return {} diff --git a/src/Util.luau b/src/Util.luau new file mode 100644 index 0000000..199a12d --- /dev/null +++ b/src/Util.luau @@ -0,0 +1,36 @@ +local function isEmpty(value) + if typeof(value) == "table" then + return next(value) == nil + end + + return value == nil +end + +local function areEqual(...) + local args = { ... } + local first = table.remove(args, 1) + + for _, value in args do + if first ~= value then + return false + end + end + + return true +end + +local function normalizeIndex(index, length) + if index == 0 then + return 1 + elseif index < 0 then + return index + length + 1 + end + + return index +end + +return { + isEmpty = isEmpty, + areEqual = areEqual, + normalizeIndex = normalizeIndex, +} diff --git a/src/Util/equalObjects.luau b/src/Util/equalObjects.luau deleted file mode 100644 index be3eb8d..0000000 --- a/src/Util/equalObjects.luau +++ /dev/null @@ -1,32 +0,0 @@ ---!strict -local _T = require(script.Parent.Parent.Types) - ---[=[ - @function equalObjects - @within Sift - - @param ... ...table -- The tables to compare. - @return boolean -- Whether or not the tables are equal. - - Compares two or more tables to see if they are equal. - - ```lua - local a = { hello = "world" } - local b = { hello = "world" } - - local equal = EqualObjects(a, b) -- true - ``` -]=] -local function equalObjects(...: _T.Table): boolean - local firstItem = select(1, ...) - - for i = 2, select("#", ...) do - if firstItem ~= select(i, ...) then - return false - end - end - - return true -end - -return equalObjects diff --git a/src/Util/func.luau b/src/Util/func.luau deleted file mode 100644 index 241013c..0000000 --- a/src/Util/func.luau +++ /dev/null @@ -1,15 +0,0 @@ -local function truthy() - return true -end - -local function noop() end - -local function returned(...) - return ... -end - -return { - truthy = truthy, - noop = noop, - returned = returned, -} diff --git a/src/Util/init.luau b/src/Util/init.luau deleted file mode 100644 index cb5ec52..0000000 --- a/src/Util/init.luau +++ /dev/null @@ -1,5 +0,0 @@ -return { - equalObjects = require(script.equalObjects), - func = require(script.func), - isEmpty = require(script.isEmpty), -} diff --git a/src/Util/isEmpty.luau b/src/Util/isEmpty.luau deleted file mode 100644 index 8cdc666..0000000 --- a/src/Util/isEmpty.luau +++ /dev/null @@ -1,26 +0,0 @@ ---!strict -local _T = require(script.Parent.Parent.Types) - ---[=[ - @function isEmpty - @within Sift - @since v0.0.1 - - @param table table -- The table to check. - @return boolean -- Whether or not the table is empty. - - Checks whether or not a table is empty. - - ```lua - local a = {} - local b = { hello = "world" } - - local value = isEmpty(a) -- true - local value = isEmpty(b) -- false - ``` -]=] -local function isEmpty(table: _T.Table): boolean - return next(table) == nil -end - -return isEmpty diff --git a/src/init.luau b/src/init.luau index 0882756..754dc10 100644 --- a/src/init.luau +++ b/src/init.luau @@ -1,60 +1,22 @@ ---!strict -local Types = require(script.Types) +-- local T = require("@Sift/Types") --[=[ @class Sift - Sift is a library for manipulating arrays. It provides a number of - functions for manipulating arrays (lists), dictionaries, and sets. - - Sift is comprised of a number of submodules. Each submodule provides - a number of functions for manipulating a specific type of data, and - can be accessed via their respective names within the Sift module - (e.g. `Sift.Array.At()`), or accessed directly (e.g. `local At = require(Sift.Array.At)`). - - Some methods and modules also have aliases, which can are documented in the - corresponding submodule/method's documentation. - - See the individual submodule pages for full documentation. - - The Luau types `Dictionary`, `Array` (aliased as `List`) and `Set` are exported from the Sift module (e.g. they can be used via `Sift.Array`), but are also available from [Sift.Types]. + Sift is a library for working with immutable data structures. It provides a collection of methods for working with arrays, dictionaries and sets. ]=] local Sift = { - Array = require(script.Array), - Dictionary = require(script.Dictionary), - Set = require(script.Set), - - None = require(script.None), - Types = require(script.Types), + Array = require("@Sift/Array"), + Dictionary = require("@Sift/Dictionary"), + Set = require("@Sift/Set"), - equalObjects = require(script.Util.equalObjects), - isEmpty = require(script.Util.isEmpty), + None = require("@Sift/None"), + Types = require("@Sift/Types"), - meta = require(script.Metadata), + equalObjects = require("@Sift/Util/equalObjects"), + isEmpty = require("@Sift/Util/isEmpty"), } Sift.List = Sift.Array ---- @prop Array Array ---- @within Sift - ---- @prop List Array ---- @within Sift ---- @tag Alias - ---- @prop Dictionary Dictionary ---- @within Sift - ---- @prop Set Set ---- @within Sift - ---- @prop Types Types ---- @within Sift - -export type Dictionary = Types.Dictionary - -export type Array = Types.Array -export type List = Array -export type Set = Types.Set - return Sift diff --git a/test.project.json b/test.project.json deleted file mode 100644 index c762d13..0000000 --- a/test.project.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "SiftTest", - "tree": { - "$className": "DataModel", - "ServerScriptService": { - "$className": "ServerScriptService", - "Sift": { - "$path": "default.project.json" - } - }, - "TestService": { - "$className": "TestService", - "$properties": { - "ExecuteWithStudioRun": true - }, - "Packages": { - "$className": "Folder", - "TestEZ": { - "$path": "modules/testez" - } - }, - "TestRunner": { - "$path": "TestRunner.server.lua" - } - }, - "Players": { - "$className": "Players", - "$properties": { - "CharacterAutoLoads": false - } - } - } -} diff --git a/wally.toml b/wally.toml index 1ccbfd2..e6588b6 100644 --- a/wally.toml +++ b/wally.toml @@ -1,7 +1,7 @@ [package] name = "csqrl/sift" description = "Immutable data library for Luau" -version = "0.0.9" +version = "0.1.0" registry = "https://github.com/upliftgames/wally-index" realm = "shared" exclude = ["**"]