-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add persistent queues * add changeset * add README for rescript-queue * add website content * fix doc link * update README * explain deque * update lock * prepare publish * update README * sync docs * chore --------- Co-authored-by: Hyeseong Kim <[email protected]>
- Loading branch information
Showing
29 changed files
with
454 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"rescript-queue": major | ||
--- | ||
|
||
Initial release of rescript-queue |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
src/*.mjs linguist-generated | ||
src/*.tsx linguist-generated | ||
tests/*.mjs linguist-generated |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
*.coverage | ||
|
||
/coverage/ | ||
/lib/ | ||
/dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# ReScript Queue | ||
|
||
[![Package Version](https://img.shields.io/npm/v/rescript-qeueue)](https://www.npmjs.com/package/rescript-queue) | ||
[![License - MIT](https://img.shields.io/npm/l/rescript-queue)](#license) | ||
|
||
`rescript-queue` is a **persistent queue and deque** data structure that can be used in ReScript and JavaScript. | ||
|
||
**_Persistent_** | ||
|
||
Any function that changes the queue returns a new instance of it while not modifying the original queue. Just like any strings or numbers, queues are treated as immutable values. | ||
|
||
**_Queue_** | ||
|
||
A queue is a data structure that follows the First-In-First-Out (FIFO) principle. This means that the first element added to the queue will be the first one to be removed. | ||
|
||
**_Deque_** | ||
|
||
A deque, short for "double-ended queue", is a data structure that allows elements to be inserted and removed from both ends. Like a regular queue, it follows the FIFO principle, but it also allows for elements to be added and removed from the back, making it a "double-ended" data structure. | ||
|
||
## Rationale | ||
|
||
### Finger Tree | ||
|
||
The [**Finger Tree**](https://en.wikipedia.org/wiki/Finger_tree) data structure is a persistent data structure that allows for efficient insertion and deletion at the front and back of the queue or deque. The finger tree is divided into "fingers" which are small, constant-size sub-trees and "digits" which are individual elements. The fingers are used to represent the larger elements in the tree, while the digits are used to represent the smaller elements. | ||
|
||
It allows for better efficiency and better space complexity than the list when implementing queue and deque. | ||
|
||
1. **Efficiency**: Lists have a linear time complexity for insertion and deletion operations at the front and back of the queue, whereas finger trees have a logarithmic time complexity for these operations. This means that finger trees can be more efficient when dealing with large queues or deques. | ||
|
||
2. **Space complexity**: Lists have a linear space complexity, which means that they will use more memory as the number of elements in the queue or deque increases. Finger trees, on the other hand, have a balanced space complexity, which means that they will use less memory for large queues or deques. | ||
|
||
`rescript-queue` provides a finger tree-based implementation of a deque in ReScript. | ||
|
||
### Batch Queue | ||
|
||
`rescript-queue` provides a **Batch Queue** implementation, which is introduced from [Purely Functional Data Structures](https://doc.lagout.org/programmation/Functional%20Programming/Chris_Okasaki-Purely_Functional_Data_Structures-Cambridge_University_Press%281998%29.pdf) by Chris Okasaki. | ||
|
||
The Batch Queue is based on the idea of "batches" of elements, which are grouped together to form a single unit. | ||
|
||
The Batch Queue has two main components: a front queue and a back queue. The front queue holds the elements that have been dequeued, while the back queue holds the elements that have been enqueued. The front and back queues are both using finger tree data structure. | ||
|
||
When an element is enqueued, it is added to the back queue. If the back queue becomes too large, it is split into two smaller queues, and the front queue is concatenated with one of the smaller queues to form a new front queue. | ||
|
||
When an element is dequeued, it is removed from the front queue. If the front queue becomes too small, it is concatenated with the back queue to form a new front queue. | ||
|
||
By using the concept of "batches" the Batch Queue is able to maintain a balance between time and space complexity, and also allows for efficient insertion and deletion at the front and back of the queue, as well as efficient concatenation and splitting of the queue. | ||
|
||
## LICENSE | ||
|
||
MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "rescript-queue", | ||
"sources": [ | ||
{ | ||
"dir": "src", | ||
"subdirs": true | ||
}, | ||
{ | ||
"dir": "tests", | ||
"type": "dev" | ||
} | ||
], | ||
"package-specs": [ | ||
{ | ||
"module": "es6", | ||
"in-source": true | ||
} | ||
], | ||
"suffix": ".mjs", | ||
"external-stdlib": "@rescript/std", | ||
"bs-dev-dependencies": [ | ||
"@dusty-phillips/rescript-zora" | ||
], | ||
"gentypeconfig": { | ||
"language": "typescript", | ||
"shims": {}, | ||
"generatedFileExtension": "" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
{ | ||
"name": "rescript-queue", | ||
"version": "0.1.0", | ||
"description": "Persistent Queue & Deque implementation in ReScript", | ||
"license": "MIT", | ||
"author": { | ||
"name": "Hyunwoo Nam" | ||
}, | ||
"keywords": [ | ||
"rescript", | ||
"data-structure", | ||
"immutable", | ||
"queue", | ||
"deque" | ||
], | ||
"sideEffects": false, | ||
"type": "module", | ||
"main": "./dist/index.mjs", | ||
"types": "./dist/index.d.ts", | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.mjs", | ||
"require": "./dist/index.cjs" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"scripts": { | ||
"res:build": "rescript build -with-deps", | ||
"res:watch": "rescript build -w", | ||
"res:clean": "rescript clean", | ||
"bundle": "nanobundle build --clean", | ||
"prepack": "yarn res:build && yarn bundle", | ||
"test": "node tests/deque_test.mjs | faucet" | ||
}, | ||
"files": [ | ||
"dist", | ||
"src/*.res", | ||
"src/*.resi", | ||
"bsconfig.json" | ||
], | ||
"dependencies": { | ||
"@rescript/std": "^10.1.0" | ||
}, | ||
"devDependencies": { | ||
"@dusty-phillips/rescript-zora": "git+https://github.com/reason-seoul/rescript-zora", | ||
"c8": "^7.12.0", | ||
"faucet": "^0.0.3", | ||
"nanobundle": "^1.3.6", | ||
"rescript": "^10.0.1", | ||
"typescript": "^4.9.4" | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
packages/vector/src/Deque.resi → packages/queue/src/Deque.resi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,33 @@ | ||
/** | ||
Persistent Deque | ||
|
||
See FingerTree.res for implementation. | ||
For pushing, popping, peeking, time complexity is O(1) amortized. | ||
*/ | ||
type t<'a> | ||
|
||
let empty: t<'a> | ||
|
||
@genType | ||
let make: unit => t<'a> | ||
|
||
@genType | ||
let pushFront: (t<'a>, 'a) => t<'a> | ||
|
||
@genType | ||
let pushBack: (t<'a>, 'a) => t<'a> | ||
|
||
@genType | ||
let popFront: t<'a> => t<'a> | ||
|
||
@genType | ||
let popBack: t<'a> => t<'a> | ||
|
||
@genType | ||
let peekFront: t<'a> => option<'a> | ||
|
||
@genType | ||
let peekBack: t<'a> => option<'a> | ||
|
||
@genType | ||
let toArray: t<'a> => array<'a> |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Batch Queue (Chris Okasaki's) | ||
*/ | ||
type t<'a> = (list<'a>, list<'a>) | ||
|
||
let empty = (list{}, list{}) | ||
let make = () => empty | ||
|
||
let isEmpty = ((f, _)) => Belt.List.size(f) == 0 | ||
|
||
let checkf = fr => | ||
switch fr { | ||
| (list{}, r) => (Belt.List.reverse(r), list{}) | ||
| q => q | ||
} | ||
|
||
let snoc = ((f, r), x) => checkf((f, list{x, ...r})) | ||
let head = q => | ||
switch q { | ||
| (list{}, _) => raise(Not_found) | ||
| (list{x, ..._}, _) => x | ||
} | ||
|
||
let tail = q => | ||
switch q { | ||
| (list{}, _) => raise(Not_found) | ||
| (list{_, ...f}, r) => checkf((f, r)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
type t<'a> | ||
|
||
let empty: t<'a> | ||
|
||
@genType | ||
let make: unit => t<'a> | ||
|
||
@genType | ||
let isEmpty: t<'a> => bool | ||
|
||
@genType | ||
let snoc: (t<'a>, 'a) => t<'a> | ||
|
||
@genType | ||
let head: t<'a> => 'a // unsafe | ||
|
||
@genType | ||
let tail: t<'a> => t<'a> // unsafe |
Oops, something went wrong.