Lazy evaluation list with high tree-shaking affinity and easy customization.

Overview

npm version

Lazy evaluation list with high tree-shaking affinity and easy customization.

Features

  • ๐ŸŽ Lazy Evaluation: The collections are only enumerated to the minimum necessary. Infinite sequences are supported.
  • ๐ŸŽ„ Tree-Shakeable: Only the features you use will be bundled.
  • ๐Ÿ‘ป Async Iterator Support: Iterable can also be seamlessly treated as Async Iterator.
  • ๐Ÿ“Ž Easy-Customization: You can easily create the functions you need by yourself. In this way.
  • ๐Ÿ—‚ Rxjs-like Syntax: To achieve tree-shaking, we use an rxjs-like syntax.
  • โœ… Simple Equality Strategy: It uses a simple Equality Strategy.
  • ๐Ÿ’ฏ All Typed: The whole thing is written in TypeScript, which also provides completion for type conversion between operators.
  • ๐Ÿ’จ No dependencies
import {from, map, take} from 'leseq';

const result1 = from([1,2,3,4,5]).pipe(
  map(i => i * i),
  take(3)
).toArray();

//result1: [1,4,9]

This is the result of bundle visualizer in the example above (1.21KB gzipped).

Resource

Advanced

Getting Started

npm install leseq

If you are using Async Iterable and "target " in tsconfig.json is smaller than "es2018", you must add "ES2018.AsyncGenerator " and "ES2018.AsyncIterable " in tsconfig.json/lib or the type will not display properly.

{
  "compilerOptions": {
    "target": "es6",
    "lib": ["DOM", "ES6", "ES2018.AsyncGenerator", "ES2018.AsyncIterable"]
  }
}

Iterable

import {from, map, take, find, range, reverse, filter} from 'leseq';

const result1 = from([1,2,3,4,5]).pipe(
  map(i => i * i),
  take(3)
)

for (const one of result1) {
  console.log(one)
}

//result: 1
//result: 4
//result: 9

const result2 = from([1,2,3,4,5]).pipe(
  filter(i => i % 2 == 0)
).value(
  find(i => i > 2)
);

//result2: 4

//lazy
const result3 = range(1, 10000000).pipe(
  take(3),
  reverse(),
  map((i) => i * i)
).toArray();

//result3: [9,4,1]

Async Iterable

import {from, mapAsync, filterAsync, fromAsAsync, findAsync, toAsync} from 'leseq';

const sleep = (milliseconds: number) => new Promise(resolve => setTimeout(resolve,milliseconds));

//from iterable to async iterable.
const result1 = await from([1,2,3,4,5]).value(toAsync()).pipe(
  mapAsync(async i => {
    await sleep(1000);
    return i * i;
  }),
  filterAsync(async i => i % 2 == 0)
).toArrayAsync();

//5 seconds later... result1: [4,16]

const result2 = await fromAsAsync([1,2,3,4,5]).pipe(
  mapAsync(async i => {
    await sleep(1000);
    return i * i;
  }),
  filterAsync(async i => i % 2 == 0)
).valueAsync(findAsync());

//2 seconds later... result2: 4

const result3 = await fromConcatAsAsync([1,2],[3,4]).pipe(
  mapAsync(async i => {
    await sleep(1000);
    return i * i;
  }),
);

for await (const one of result3) {
  console.log(one);
}

//1 seconds later... result: 1
//2 seconds later... result: 4
//3 seconds later... result: 9
//4 seconds later... result: 16

Usage

You can generate a sequence(Seq<T>/AsyncSeq<T> object) with Generator, perform transformations and other operations with any number of Operators, and convert it to a value with Value.

// sync iterator
SyncSource = 
  Generators(ex: from, fromConcat, ..etc) | 
  SyncSource.pipe(
    ...SyncOperators(ex: map, filter, ...etc)
  );

value = SyncSource.value(SyncValues(ex: find,some, ...etc));

// async iterator
AsyncSource = 
  AsyncGenerators(ex: fromAsAsync, fromConcatAsAsync, ...etc) |
  SyncSource.value(toAsync()) | // iterable to async iterable.
  AsyncSource.pipe(
    ...AsyncOperators(ex: mapAsync, filterAsync, ...etc)
  );

value = await AsyncSource.valueAsync(AsyncValues(ex: findAsync,someAsync, ...etc));

Since lazy evaluation is employed, the process is not executed when pipe() is called, but only when value(valueAsync), toArray(toArrayAsync)/toMutableArray(toMutableArrayAsync), or forEach(forEachAsync) is called.

Changes from "Iterable" or Seq<T> to "Async Iterable" can be made at any time with .value(toAsync()). but Once the chain is changed to "Async Iterable" by .value(toAsync()) or other means, only the asynchronous version of Operator/Value can be used in the same chain thereafter. This is because, in principle, it is impossible to change from an "Async Iterable" to "Iterable".

The predefined Generators/Operators/Values are as follows. And all of them have asynchronous versions(xxxAsAsync or xxxAsync).

If the function you want to use does not exist, you can also define your own Operator/Value function in this way.

Predefined Generators

Generator Description
from Generates a sequence from an iterable object. (async version: fromAsAsync )
fromConcat Generates a concatenated sequence of multiple iterable objects. (async version: fromConcatAsAsync )
fromValue Generates a sequence from a single value. (async version: fromValueAsAsync )
range Generates a sequential number sequence. (async version: rangeAsAsync )
repeat Generates a sequence in which the specified value is repeated a specified number of times. (async version: repeatAsAsync )

Predefined Operators

It is used within the pipe method of the Seq<T> object. Any number of operators can be connected.

Operator Description
chunk Returns a sequence divided into array of the specified size. (async version: chunkAsync )
concat Returns a sequence in which the current sequence and the specified sequence are concatenated. (async version: concatAsync )
concatValue Returns the sequence to which the specified value is added. (async version: concatValueAsync )
difference Returns the sequence that is the difference set between the current sequence and the specified sequence. (async version: differenceAsync )
filter Returns a sequence that has been filtered by the specified condition. (async version: filterAsync )
flatten Returns a flattened sequence. (async version: flattenAsync )
groupBy Returns a sequence grouped by a specified key. (async version: groupByAsync )
intersect Returns a sequence that is the product set of the current sequence and the specified sequence. (async version: intersectAsync )
map Returns the sequence in which each element has been transformed by the specified transformation function. (async version: mapAsync )
orderBy Returns a sequence sorted by a specified key. (async version: orderByAsync )
reverse Returns a sequence in reverse order of the current sequence. (async version: reverseAsync )
scan Returns the resulting sequence after applying the aggregate function to the elements of the current sequence. (async version: scanAsync )
skip Returns the sequence with the specified number of skips. (async version: skipAsync )
skipWhile Returns the sequence of elements skipped while matching the condition. (async version: skipWhileAsync )
take Returns a sequence that enumerates the specified number of items. (async version: takeAsync )
takeWhile Returns a sequence to be enumerated only while the condition is matched. (async version: takeWhileAsync )
tap Run side effects. (async version: tapAsync )
union Returns a sequence that is the union set of the current sequence and the specified sequence. (async version: unionAsync )
uniq Returns a deduplicated sequence. (async version: uniqAsync )
finalize Invokes a specified action after the source iterable sequence terminates gracefully or exceptionally. (async version: finalizeAsync )

Predefined Values

Generates a value from a sequence. Used in the value method of the Seq<T> object.

Value Description
toAsync Converts the current sequence to AsyncSeq<T> and returns it.
every Returns whether or not all elements of a sequence meet the specified conditions. (async version: everyAsync )
find Returns the first element that satisfies the condition. If no element satisfying the condition is found, an error is thrown. (async version: findAsync )
findOrDefault Returns the first element that satisfies the condition. If no element is found that satisfies the condition, it returns the specified default value. (async version: findOrDefaultAsync )
reduce Returns the result of applying the aggregate function to the elements of the current sequence. (async version: reduceAsync )
some Returns whether or not any element of the sequence satisfies the specified condition. (async version: someAsync )
You might also like...

JSPro is nothing but JavaScript Prototypes! The publisher is too lazy to write full name that's why it's just JSPro.

JSPro is nothing but JavaScript Prototypes! The publisher is too lazy to write full name that's why it's just JSPro. Whatever, it's a library of hundreds of awesome JavaScript Prototypes (you may know it as dot function) for lazy programmers. Just install the package with a little effort and leave the blames for the publisher.

Mar 10, 2022

A lazy plugin for printing local network when starting NodeJS server. I made this so you don't have to.

A lazy plugin for printing local network when starting NodeJS server. I made this so you don't have to.

lazy-net A simple, lightweight plugin for printing local network when starting Node.js or Express.js server. I made this so you don't have to. There a

Feb 10, 2022

A small (~600B gzip), useful set of methods for lazy iteration of iterables.

@ricokahler/lazy ยท A small (~600B gzip*), useful set of methods for lazy iteration of iterables. Why this lazy lib? Do I even need a lazy lib? Install

Sep 10, 2022

Program that helps you to be more lazy :)

IFL (I F#cking lazy) IFL - is a program build with electron & react. Main goal of this project is to help you be more productive with adding new songs

Aug 31, 2022

Lazy minting of ERC721 NFTs using EIP712 standard for typed, structured data. โœจ

ERC721 - Signature minting Lazy minting of ERC721 NFTs using EIP712 standard for typed, structured data. โœจ How it works Lazy minting or Signature mint

Oct 20, 2022

A modern lazy loading library for images.

Layzr.js A modern lazy loading library for images. Demo Page Getting Started Follow these steps: Install Setup Images Instantiate Review Options Revie

Dec 25, 2022

Simple lazy responsive starter kit for CraftCMS 4 Projects.

Simple lazy responsive starter kit for CraftCMS 4 Projects.

Lazy Craft CMS 4 Boilerplate Simple lazy responsive starter kit for CraftCMS 4 Projects. Requirements RTFM Craft CMS 4 Requirements Configs Duplicate

Sep 2, 2022

Finally, a simple, lightweight (0.6kb), pure JavaScript image lazy loader that even works in IE* using the IntersectionObserver API

Simply Lazy A simple & lightweight (0.6kb), pure JavaScript image lazy loader that even works in IE* utilizing the built in IntersectionObserver API i

Dec 26, 2022
Comments
  • Suggestion: An alias method to output readonly array for Seq

    Suggestion: An alias method to output readonly array for Seq

    Hello,

    This is a suggestion to support ReadonlyArray<T>. In my opinion, ReadonlyArray is always a preferable choice than mutable one. (So they should be toMutableArray() and toArray() though, I hesitate to break backward compatibility)

    Also, I think some operators are able to support that interface i.e. the result of groupBy. I would commit for some enhancement if you feel positive against that.

    Thanks!

    opened by hachibeeDI 7
  • Suggestions to make it easier to exclude null and undefined

    Suggestions to make it easier to exclude null and undefined

    Hello.

    I would like to suggest additional operators that will help exclude null and undefined from the sequence.

    I think you'll need ritual code like filter(i => i! == null && i! == undefined) or map(i => i !!) to exclude null and undefined from the sequence. I found a hint from Kotlin to solve this problem and used it as a reference.

    I hope this proposal is meaningful to the project.

    Thank you for reading.

    PS: I wrote the composition using Google Translate. Please forgive me for the dull sentences ...

    opened by samunohito 4
  • Fixed (probably unintentional) omission of await description.

    Fixed (probably unintentional) omission of await description.

    Hello. Thank you for all your help on another matter.

    I was reviewing the test code and found that an await was missing, perhaps unintentionally. (I hope you can check the diff for the specific location).

    If it is unintentional, I hope you will consider this proposal. If it is intentional, you may reject this pull request.

    Thank you for reading.

    opened by samunohito 2
Releases(v1.10.0)
Owner
Masanori Onoue
Microsoft MVP for C# 2012/7~2017/6. "Livet" project owner has been transferred to @runceel
Masanori Onoue
Fast and lightweight dependency-free vanilla JavaScript polyfill for native lazy loading / the awesome loading='lazy'-attribute.

loading="lazy" attribute polyfill Fast and lightweight vanilla JavaScript polyfill for native lazy loading, meaning the behaviour to load elements rig

Maximilian Franzke 571 Dec 30, 2022
OpenXAI : Towards a Transparent Evaluation of Model Explanations

OpenXAI : Towards a Transparent Evaluation of Model Explanations Website | arXiv Paper OpenXAI is the first general-purpose lightweight library that p

null 121 Dec 28, 2022
Project of "Web Development" course for the Bachelor's degree in Computer Engineering, taken at the University of Pisa. Final evaluation: 30/30.

La battaglia della Meloria Welcome! This is the ???? version of the README file. Click here for ???? version. Introduction Historical reinterpretation

Daniel Namaki 3 Oct 6, 2022
High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more, that detects any visibility changes triggered through user interaction, CSS or JavaScript without configuration.

lazysizes lazysizes is a fast (jank-free), SEO-friendly and self-initializing lazyloader for images (including responsive images picture/srcset), ifra

Alexander Farkas 16.6k Jan 1, 2023
Salazar - a Discord bot that is easy to customize and configure, aiming at the possibility of customization for the user

Salazar is a Discord bot that is easy to customize and configure, aiming at the possibility of customization for the user. This is the BETA version, which uses the current version of Node.js.

guto 5 Dec 7, 2022
A starter and demo project for Keycloakify v6 - Component level customization.

A starter/demo project for Keycloakify โš ๏ธ Please read the two following notices โš ๏ธ This starter is for Component-level customization, if you only want

Joseph Garrone 12 Dec 26, 2022
Project to manage multiple emails at once with lots of customization. You can send and receive emails. Desktop notifications can be modified.

Technologies Used React Redux Tailwind CSS Features Admin dashboard User settings and or user dashboard send emails recive emails Connections through

Multi Email 9 Dec 17, 2022
A non-overflowing `console.table` alternative with customization options.

nice-table A non-overflowing console.table alternative with customization options. Usage import { createTable } from 'nice-table'; type Person = {

Tim van Dam 5 Aug 4, 2022
This is a template for a peripheral customization PWA.

Peripheral Customization PWA This repository contains a template Progressive Web App (PWA) that can be used to customize peripherals. The template was

Google 3 Sep 30, 2022
The brand new @shopify/flash-list high performance list component can be used on TV as well as on phones!

FlashListTV The brand new @shopify/flash-list high performance list component can be used on TV as well as on phones! Quick start: Clone this repo Cha

Douglas Lowder 4 Oct 27, 2022