diff --git a/async/unstable_channel.ts b/async/unstable_channel.ts index b82837a685bd..db495d805c2c 100644 --- a/async/unstable_channel.ts +++ b/async/unstable_channel.ts @@ -1,7 +1,7 @@ // Copyright 2018-2026 the Deno authors. MIT license. // This module is browser compatible. -import { Deque } from "@std/data-structures/unstable-deque"; +import { Deque } from "@std/data-structures/deque"; /** Internal node for the FIFO sender waiting queue. */ interface SenderNode { diff --git a/data_structures/deno.json b/data_structures/deno.json index da895e9caadc..f88e662198a4 100644 --- a/data_structures/deno.json +++ b/data_structures/deno.json @@ -8,9 +8,9 @@ "./binary-search-tree": "./binary_search_tree.ts", "./unstable-binary-search-tree": "./unstable_binary_search_tree.ts", "./comparators": "./comparators.ts", + "./deque": "./deque.ts", "./red-black-tree": "./red_black_tree.ts", "./unstable-2d-array": "./unstable_2d_array.ts", - "./unstable-rolling-counter": "./unstable_rolling_counter.ts", - "./unstable-deque": "./unstable_deque.ts" + "./unstable-rolling-counter": "./unstable_rolling_counter.ts" } } diff --git a/data_structures/unstable_deque.ts b/data_structures/deque.ts similarity index 86% rename from data_structures/unstable_deque.ts rename to data_structures/deque.ts index 604cda924a9f..090c0d224365 100644 --- a/data_structures/unstable_deque.ts +++ b/data_structures/deque.ts @@ -9,8 +9,6 @@ const MIN_SHRINK_CAPACITY = 64; * following the `ReadonlyArray` / `ReadonlyMap` / `ReadonlySet` pattern. * A `Deque` is directly assignable to `ReadonlyDeque`. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @typeParam T The type of the values stored in the deque. */ export type ReadonlyDeque = Pick< @@ -65,11 +63,9 @@ function nextPowerOfTwo(n: number): number { * | toArray() | O(n) | O(n) | * | Deque.from() | O(n) | O(n) | * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Usage * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque(); @@ -95,11 +91,9 @@ export class Deque implements Iterable, ReadonlyDeque { /** * Creates an empty deque, optionally populated from an iterable. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Creating an empty deque * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque(); @@ -108,7 +102,7 @@ export class Deque implements Iterable, ReadonlyDeque { * * @example Creating a deque from an iterable * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -167,11 +161,9 @@ export class Deque implements Iterable, ReadonlyDeque { /** * The number of elements in the deque. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Getting the length * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -187,11 +179,9 @@ export class Deque implements Iterable, ReadonlyDeque { /** * Checks if the deque contains no elements. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Checking if the deque is empty * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque(); @@ -210,11 +200,9 @@ export class Deque implements Iterable, ReadonlyDeque { /** * Append one or more values to the back of the deque. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Pushing values to the back * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque(); @@ -243,11 +231,9 @@ export class Deque implements Iterable, ReadonlyDeque { * in argument order, so `pushFront(1, 2, 3)` results in front-to-back order * `[1, 2, 3, ...existing]`. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Pushing values to the front * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([4, 5]); @@ -276,11 +262,9 @@ export class Deque implements Iterable, ReadonlyDeque { /** * Remove and return the back element, or `undefined` if the deque is empty. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Popping from the back * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -303,11 +287,9 @@ export class Deque implements Iterable, ReadonlyDeque { /** * Remove and return the front element, or `undefined` if the deque is empty. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Popping from the front * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -332,11 +314,9 @@ export class Deque implements Iterable, ReadonlyDeque { * front to back. The gap is closed by shifting whichever side (front or back) * has fewer elements to move, so removals near either end are fast. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Removing the first even number * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3, 4]); @@ -360,11 +340,9 @@ export class Deque implements Iterable, ReadonlyDeque { * `undefined` for out-of-range indices. The gap is closed by shifting * whichever side (front or back) has fewer elements to move. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Removing by index * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([10, 20, 30, 40]); @@ -374,7 +352,7 @@ export class Deque implements Iterable, ReadonlyDeque { * * @example Removing with a negative index * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([10, 20, 30, 40]); @@ -395,11 +373,9 @@ export class Deque implements Iterable, ReadonlyDeque { * Return the first element matching the predicate, scanning from front to * back, without removing it. Returns `undefined` if no match is found. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Finding the first even number * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3, 4]); @@ -421,11 +397,9 @@ export class Deque implements Iterable, ReadonlyDeque { * Return the index of the first element matching the predicate, scanning * from front to back. Returns `-1` if no match is found. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Finding the index of the first even number * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3, 4]); @@ -445,11 +419,9 @@ export class Deque implements Iterable, ReadonlyDeque { * Return the front element without removing it, or `undefined` if the deque * is empty. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Peeking at the front * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -468,11 +440,9 @@ export class Deque implements Iterable, ReadonlyDeque { * Return the back element without removing it, or `undefined` if the deque * is empty. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Peeking at the back * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -492,11 +462,9 @@ export class Deque implements Iterable, ReadonlyDeque { * indices count from the back (`-1` is the last element). Returns `undefined` * for out-of-range indices. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Accessing elements by index * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([10, 20, 30, 40]); @@ -519,11 +487,9 @@ export class Deque implements Iterable, ReadonlyDeque { * {@link https://tc39.es/ecma262/#sec-samevaluezero | SameValueZero} * comparison (like {@linkcode Array.prototype.includes}). * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Checking for membership * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -533,7 +499,7 @@ export class Deque implements Iterable, ReadonlyDeque { * * @example NaN is found (SameValueZero semantics) * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, NaN, 3]); @@ -544,9 +510,19 @@ export class Deque implements Iterable, ReadonlyDeque { * @returns `true` if the deque contains the value, otherwise `false`. */ includes(value: T): boolean { - for (let i = 0; i < this.#length; i++) { - const el = this.#buffer[(this.#head + i) & this.#mask]; - // SameValueZero: === for everything except NaN + const buf = this.#buffer; + const head = this.#head; + const len = this.#length; + const cap = this.#mask + 1; + const firstLen = Math.min(len, cap - head); + // SameValueZero: === for everything except NaN + for (let i = 0; i < firstLen; i++) { + const el = buf[head + i]; + if (el === value || (el !== el && value !== value)) return true; + } + const rem = len - firstLen; + for (let i = 0; i < rem; i++) { + const el = buf[i]; if (el === value || (el !== el && value !== value)) return true; } return false; @@ -555,11 +531,9 @@ export class Deque implements Iterable, ReadonlyDeque { /** * Remove all elements and release the backing buffer. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Clearing the deque * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -581,11 +555,9 @@ export class Deque implements Iterable, ReadonlyDeque { * {@linkcode Array.prototype.filter}. The predicate is called once per * element in front-to-back order. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Retaining only odd numbers * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3, 4, 5]); @@ -617,11 +589,9 @@ export class Deque implements Iterable, ReadonlyDeque { * Return a shallow copy of the deque's contents as an array, in * front-to-back order. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Converting to an array * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -631,21 +601,24 @@ export class Deque implements Iterable, ReadonlyDeque { * @returns An array containing the deque's elements in order. */ toArray(): T[] { - const result = new Array(this.#length); - for (let i = 0; i < this.#length; i++) { - result[i] = this.#buffer[(this.#head + i) & this.#mask] as T; - } + const buf = this.#buffer; + const head = this.#head; + const len = this.#length; + const cap = this.#mask + 1; + const result = new Array(len); + const firstLen = Math.min(len, cap - head); + for (let i = 0; i < firstLen; i++) result[i] = buf[head + i] as T; + const rem = len - firstLen; + for (let i = 0; i < rem; i++) result[firstLen + i] = buf[i] as T; return result; } /** * Create a new deque from an array-like, iterable, or existing deque. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Creating a deque from an array * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = Deque.from([1, 2, 3]); @@ -654,7 +627,7 @@ export class Deque implements Iterable, ReadonlyDeque { * * @example Creating a deque from an existing deque * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const original = new Deque([1, 2, 3]); @@ -673,11 +646,9 @@ export class Deque implements Iterable, ReadonlyDeque { * Create a new deque from an array-like, iterable, or existing deque, with * a mapping function applied to each element. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Creating a deque with a mapping function * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = Deque.from([1, 2, 3], { map: (v) => v * 10 }); @@ -756,11 +727,9 @@ export class Deque implements Iterable, ReadonlyDeque { * Iterate over the deque's elements from front to back. Non-destructive * (unlike {@linkcode BinaryHeap}). * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Iterating over the deque * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -778,11 +747,9 @@ export class Deque implements Iterable, ReadonlyDeque { /** * Iterate over the deque's elements from back to front. * - * @experimental **UNSTABLE**: New API, yet to be vetted. - * * @example Iterating in reverse * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque([1, 2, 3]); @@ -802,7 +769,7 @@ export class Deque implements Iterable, ReadonlyDeque { * * @example Usage * ```ts - * import { Deque } from "@std/data-structures/unstable-deque"; + * import { Deque } from "@std/data-structures/deque"; * import { assertEquals } from "@std/assert"; * * const deque = new Deque(); @@ -813,9 +780,14 @@ export class Deque implements Iterable, ReadonlyDeque { static #copyBuffer(source: Deque, capacity: number): (T | undefined)[] { const buffer = new Array(capacity); - for (let i = 0; i < source.#length; i++) { - buffer[i] = source.#buffer[(source.#head + i) & source.#mask]; - } + const src = source.#buffer; + const head = source.#head; + const len = source.#length; + const srcCap = source.#mask + 1; + const firstLen = Math.min(len, srcCap - head); + for (let i = 0; i < firstLen; i++) buffer[i] = src[head + i]; + const rem = len - firstLen; + for (let i = 0; i < rem; i++) buffer[firstLen + i] = src[i]; return buffer; } diff --git a/data_structures/unstable_deque_test.ts b/data_structures/deque_test.ts similarity index 99% rename from data_structures/unstable_deque_test.ts rename to data_structures/deque_test.ts index 34bfd8ff7299..89339e1e2755 100644 --- a/data_structures/unstable_deque_test.ts +++ b/data_structures/deque_test.ts @@ -1,7 +1,7 @@ // Copyright 2018-2026 the Deno authors. MIT license. import { assertEquals, assertStrictEquals, assertThrows } from "@std/assert"; -import { Deque, type ReadonlyDeque } from "./unstable_deque.ts"; +import { Deque, type ReadonlyDeque } from "./deque.ts"; import { MyMath } from "./_test_utils.ts"; // -- Construction -- diff --git a/data_structures/mod.ts b/data_structures/mod.ts index 4454bdd9fb48..a0527f432803 100644 --- a/data_structures/mod.ts +++ b/data_structures/mod.ts @@ -28,4 +28,5 @@ export * from "./binary_heap.ts"; export * from "./binary_search_tree.ts"; export * from "./comparators.ts"; +export * from "./deque.ts"; export * from "./red_black_tree.ts";