• Stars
    star
    1,416
  • Rank 31,999 (Top 0.7 %)
  • Language
    JavaScript
  • License
    ISC License
  • Created almost 9 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A utility library for modern JavaScript.

Trine

Join the chat at https://gitter.im/jussi-kalliokoski/trine

Build Status Coverage Status

A utility library for modern JavaScript.

Trine is a utility library geared at tapping the full potential of functional programming in JS, in the vein of lodash, underscore and Ramda.

See the latest docs/documentation for a full API reference.

Why?

At this point, you should be asking yourself: "why yet another utility library", and you'd be right in asking so. Ramda argues that lodash and underscore put the data in the wrong place: at the first parameter of the function, while it should be at the last position. They're both (subjectively) wrong: the natural place for data in JS is the this parameter.

Functional programming in JS is awkward. ES5 introduced some improvements, and ES6 introduces even more. However, even if you're writing ES6 today, you are probably still seeing code like this when attempting to write in a functional style:

flatten(
    items
        .filter(isOk)
        .map(toOtherType)
)

And this is just a simple example. The data as an argument style just doesn't fit in well with the builtins of JS, and makes it hard to reason about the order of transformations. What you'd really want to do is this:

items
    .filter(isOk)
    .map(toOtherType)
    .flatten()

but extending the builtin prototypes is a bad practice, even in non-library code, and has caused numerous issues with standardizing new features to builtins in JS. The function bind syntax proposal fixes this issue. The previous example could be written as follows:

items
    .filter(isOk)
    .map(toOtherType)
    ::flatten()

Much better. But that's not all. Let's imagine we had a custom map and reduce methods that passed each item as this to the transformer function, as well as some other helpers. This would allow us to compose using the builtins, as so:

const characters = strings
    ::map(String.prototype.split::partial(""))
    ::reduce(Array.prototype.concat)
    .sort()
    ::uniq();

But why stop there? ES6 introduces the concept of iterators to JS. Iterators are a protocol that most collection types in ES6 (Map, Set, Array, etc.) implement, by exposing a function under the Symbol.iterator symbol. This means you can also extend your custom collection types to support the same protocol, and generator functions support it too. Iterators are a very flexible abstraction over collections, and unlike memory-bound collections, can also represent infinite sets, such as the Fibonacci series or prime numbers. In a memory-bound collection an infinite number of items would require infinite memory.

Iterators, on the other hand, allow us to process only as much as we need. So let's say we wanted to find the first 5 common items (intersection) of two infinite sets, the Fibonacci series and the prime numbers. The following is a working example of Trine, as Trine's all collection methods are actually methods for iterables:

function * fibonacci () {
    let i0 = 1;
    let i1 = 0;

    while ( true ) {
        yield i0;
        [i0, i1] = [i0 + i1, i0];
    }
}

function * primes () {
    const primes = new Set();
    yield 2;

    loop: for ( let i = 3; true; i += 2 ) {
        for ( const prime of primes ) {
            if ( i % prime === 0 ) { continue loop; }
        }

        primes.add(i)
        yield i;
    }
}

const commonItems = [fibonacci(), primes()]
    ::intersection(sub)
    ::head(5)
    ::to(Array);
console.log(commonItems); // logs [2, 3, 5, 13, 89]

Using iterators also allows us to easily timebox even synchronous operations. Let's say we wanted to get the 1000 first common items, but we'd be ok with less if it would block for too long:

const deadline = Date.now() + 1000;
const commonItems = [
    fibonacci()::takeWhile(() => Date.now() < deadline),
    primes(),
]
    ::intersection(sub)
    ::head(1000)
    ::to(Array);

if ( commonItems.length < 1000 ) {
    console.error("Sorry, asked for 1000 items but got only %s :(", commonItems.length);
}

console.log(commonItems);

There are some other practical applications to this as well. Say we have a set of products, and we want to show a page that lists the first 15 items sorted ascending by price. If our product catalogue is prohibitively long, sorting all the items ascending by price would take too long. With iterators, however, we can perform this orders of magnitude faster than with in-memory collections. Trine ships with an implementation of the quicksort algorithm that works with iterators. Using this, we only do precise sorting for the 15 first items, as so:

function byPrice (b) {
    return this.price - b.price;
}

const firstPageItems = products
    ::quickSort(byPrice)
    ::head(15)
    ::to(Array);

That's it! Most of the time you won't even have to be thinking about performance, because with iterators you can just compose the manipulations to produce the result you need and good performance will be the default. I welcome all micro-benchmarks, but doing less work will always be faster than doing more work.

Maybe

Iterators have one more trick up their sleeve. They provide a handy way to wrap missing data, instead of implementing error handling at every turn. For example:

function getItemPriceById (id) {
    const result = this
        ::find(function () {
            return this.id === id;
        })
        ::map(prop("price"))
        .next();

    if ( result.done ) { throw new Error("Item not found"); }
    return result.value;
}

Modules

Trine has been designed to be modular and decoupled from the ground up. Each exposed function is in its own module, so for example if you're using Webpack, instead of a huge library, you will only be transferring the needed functions to the client.

Installation

Trine is available on npm:

npm install --save trine

License

Trine is ISC licensed. See the LICENSE document for more information.

Contributing

The issues are a good place to start. Whether you're having a bug or fix one, have a knack for design and want to improve the appeal of Trine, want to improve the documentation, add a test case, propose a feature or just ask for help, please do. All (friendly) contributions are welcome, as long as they're not malicious.

Similar / Compatible / Complementary Libraries

  • curry-this - currying made simple. Works with the function bind syntax.
  • this-is-truthy - Check if this is truthy.
  • mori-ext - Function bind syntax wrappers for mori.
  • iterable-some - Array.some for iterables.
  • this-drop - Get the this object stripped of some properties.
  • Got another one? Don't be shy, add it here!

More Repositories

1

audiolib.js

audiolib.js is a powerful audio tools library for javascript.
JavaScript
670
star
2

html5Preloader.js

A javascript library to preload all kinds of content, be it text, xml, audio, video or image, with simple syntax.
JavaScript
228
star
3

sink.js

A javascript library for audio output
JavaScript
200
star
4

react-no-jsx

A pure JS alternative to JSX
JavaScript
69
star
5

babel-plugin-operator-overload

Babel plugin for overloading operators
JavaScript
67
star
6

pcmdata.js

A javascript library to read / write .wav pcm data files
JavaScript
42
star
7

node-dsp

An implementation of the DSP API
CoffeeScript
38
star
8

binary.js

Provides a very fast and robust interface for binary conversions in JavaScript
JavaScript
33
star
9

gulp-awspublish-router

A router for defining file-specific rules with gulp-awspublish
JavaScript
29
star
10

htmlentities.js

A minimal html entities decoder/encoder using DOM.
JavaScript
26
star
11

jQuery.grab

A port of Jin's grab gesture.
JavaScript
21
star
12

node-progress-bar

An STDOUT progress bar for NodeJS
JavaScript
20
star
13

merry-go-round

Merry-go-Round is a React-based component library for building amazing carousels!
JavaScript
19
star
14

polyfill-service-webpack

A webpack plugin for polyfill.io.
JavaScript
18
star
15

eslint-plugin-no-implicit-side-effects

ESLint plugin for requiring side effects to be explicit.
JavaScript
18
star
16

BrainScript

BrainScript is a scripting language that is a subset of JavaScript and inspired by Urban Müller's brainfuck.
18
star
17

gulp-spa

Define your build sources in HTML.
JavaScript
16
star
18

mike.js

JavaScript
14
star
19

web-midi-test-suite

A test suite for Web MIDI API
JavaScript
14
star
20

fft.js

A Fast Fourier Transform in JavaScript
JavaScript
13
star
21

node-cubeb

Node module for libcubeb
C++
13
star
22

vectorizer.js

A JS library for raster->vector
JavaScript
13
star
23

weakbind

Memoized bind for higher performance.
JavaScript
10
star
24

slogdriver

Stackdriver Logging / GCP Cloud Logging handler for the go 1.21 slog package.
Go
10
star
25

react-mistyped-props

Warnings for mistyped props in your React components.
JavaScript
10
star
26

simplesynth

A simple synth example for Firefox 4 Audio API
JavaScript
9
star
27

atom-npm-plus

npm integration for atom
JavaScript
8
star
28

src.js

Sample Rate Conversion for JS
JavaScript
7
star
29

btoa-atob

Command line utility to convert files to base64 and vice versa.
JavaScript
7
star
30

http.js

A HTTP utilities library for client-side applications.
JavaScript
5
star
31

macnjs

C Preprocessor for JS (or anything, really)
C
5
star
32

kakku

A backend agnostic cache layer for node.js
JavaScript
5
star
33

jin.js

A lightweight javascript library / framework
JavaScript
5
star
34

virtual-midi-keyboard

A virtual HTML5 MIDI keyboard
JavaScript
5
star
35

canvas-history.js

Binds an easy undo/redo API to Canvas 2D Drawing Context.
JavaScript
5
star
36

node-blessings

node.js port of python's blessings
JavaScript
5
star
37

asifier

JavaScript
4
star
38

dotfiles

My workflow, probably nothing you'd care about.
Vim Script
4
star
39

midinode

A NodeJS module providing cross-platform JS bindings for MIDI device control.
C++
4
star
40

grunt-pack

Packaging tasks for Grunt
JavaScript
4
star
41

setImmediate.js

A small shim for the setImmediate() that creates a callback similar to process.nextTick() on node.js
JavaScript
4
star
42

sweet-es7-async

A sweet.js macro for ES7 async functions.
JavaScript
4
star
43

par

A go library to perform slice operations (e.g. map, filter, reduce) in parallel.
Go
4
star
44

harmony.vim

Extensive JS syntax support for VIM
Vim Script
3
star
45

Featurizr

A Modernizr extension to spice up your media queries with feature queries
JavaScript
3
star
46

Colourizr

Colourizr is a color conversion tool for web use, especially CSS
JavaScript
3
star
47

Calculatoure

A slick HTML5 calculator, able to handle a multitude of mathematical things.
JavaScript
3
star
48

inceptionscript

Write JS macros in JS
JavaScript
3
star
49

gointerfacefunc

Generate function types for go interfaces for testing
Go
3
star
50

makejs

A javascript-based build tool, similar to make.
C++
2
star
51

restzilla

A RESTful API wrapper for Bugzilla
CoffeeScript
2
star
52

rawcanvas.js

Raw pixel access with WebGL, fallback with 2DContext
JavaScript
2
star
53

script-builder

Makes it easier to manage bigger script projects.
JavaScript
2
star
54

tool-belt.js

Small JS utilities I often use
JavaScript
2
star
55

grunt-fixtures2js

Convert your fixtures into a JS object for use in tests.
JavaScript
2
star
56

paramon

paramon is a tool for parsing command line arguments. Its agenda is to make it nice to make nice command line options.
JavaScript
2
star
57

fonticon-loader

Webpack loader for icons, converting them into iconfonts.
JavaScript
2
star
58

gostringenum

Generate efficient string encodings and decodings for go enums.
Go
2
star
59

mpmc

A go library to manage communications across Multiple Producers and Multiple Consumers.
Go
2
star
60

grunt-doctor.js

A grunt task for doctor.js
CoffeeScript
1
star
61

fixtures2js

The shared library for the gulp and grunt tasks.
JavaScript
1
star
62

oocubeb

ooc port of libcubeb
ooc
1
star
63

advent-of-code-2022

Advent of Code 2022 solutions
1
star
64

Solo.js

An ES6 Promise-based task queue utility.
JavaScript
1
star
65

struct.js

Structs for JS
JavaScript
1
star
66

stupid.js

The Stupid JS Style Guide
1
star
67

orbisyn

JavaScript
1
star
68

express-riak

A Riak session store adapter for Express.
JavaScript
1
star
69

concat-vs-multiplex

A benchmark of HTTP2 push multiplexing vs concatenation/bundling.
JavaScript
1
star
70

helsinkijs-2013-10-17

My slides for my talk at HelsinkiJS 2013-10-17
CoffeeScript
1
star
71

doctor.js

Formatting agnostic documentation
JavaScript
1
star
72

privateEval.js

A javascript library to allow javascript execution in a completely safe and private scope.
JavaScript
1
star
73

chai-gulp-helpers

A simple test helper to verify that your stream returns the expected files.
JavaScript
1
star
74

watch-and-run

A simple tool for running commands when files change.
JavaScript
1
star
75

kakku-redis-store

A Redis Store for Kakku.
JavaScript
1
star
76

go-prettyformat

Stringify go values
Go
1
star
77

through2-sequence

Combine streams into a sequence where input is the first stream and output is the last.
JavaScript
1
star
78

kakku-multi-store

A multi-backend Store for Kakku.
JavaScript
1
star
79

lowlite

A syntax highlighting library for NodeJS
JavaScript
1
star
80

blog

My personal blog
JavaScript
1
star
81

kakku-lru-cache-store

An in-memory LRU cache Store for Kakku
JavaScript
1
star
82

CodeExpression.js

A javascript library to parse a multitude of languages. Use cases include syntax highlighting, minifiers, etc.
JavaScript
1
star
83

gulp-fixtures2js

A gulp plugin for fixtures2js
JavaScript
1
star
84

gulp-resolver

Replace references to source files with references to generated files.
JavaScript
1
star