npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

raptorjuice

v0.2.12

Published

The JungleFresh Swiss Army Knife.

Downloads

216

Readme


RaptorJuice

Build Status

Preface

RaptorJuice originated as a utility library for Elixir. It implements iterators, type checking and other generally missed utilities in JavaScript. It is lightweight, (and may become lighter in the future) at around 6.5k uglified.

Purpose

The main goal for RaptorJuice is to implement iterators, or generator objects, with a concise and robust API.

Installation

  • Ensure that you have Node.js on your system.

RaptorJuice is entirely self contained and published on npm so all you need to do is:

npm install raptorjuice

Development

  • Ensure that you have Node.js on your system.

  • Prepare your environment by executing the following commands:

    git clone https://github.com/junglefresh/RaptorJuice.js raptorjuice
    cd raptorjuice
    npm install
    sudo npm install -g grunt-cli mocha

Testing

To automatically run tests upon saving changes to the source or tests run the following:

mocha --reporter spec ./spec/**/*.js ./spec/*.js
  • Upon execution of the following command, after each write:

    • The unit tests will be confirmed.

Building

To begin automatically building the project, run:

grunt watch
  • Please note that a Java Runtime is required due to the jsdoc dependency.

  • By executing the following command, upon each write:

    • The unit tests will be confirmed.
    • Documentation will be regenerated if all tests pass.

Demonstration

If you are interested in any of RaptorJuice's secondary functionality, please refer to the documentation. As stated above, RaptorJuice's primary goal is to create generator objects, and more specifically, to greatly simplify asynchronous iteration.

Forward Iteration

An iterator object's default direction is forward.

var gen = R.iterate([ 1, 2, 3 ]);

while(gen.remaining()) {
  console.log(gen.next());
}

As you probably expect, this prints the values: 1, 2, and 3.

Backward Iteration

Iterators can also be reversed.

var gen = R.iterate([ 1, 2, 3 ]).reversed();

while(gen.remaining()) {
  console.log(gen.next());
}

Note thate the reversed method actually makes a new iterator.

This prints the values in the array in reversed order.

Previous Values and Reverse

An example of iterator reversal follows.

var gen = R.iterate([ 1, 2, 3, 4 ]);

gen.next(); // 1
gen.next(); // 2

gen.reverse().next(); // 2
gen.reverse({ discard : true }).next(); // 3

As a convenience, a prev method also exists. It calls the reverse method, then the next method, followed by reverse again. It takes no parameters.

var gen = R.iterate([ 1, 2, 3, 4 ]);

gen.next(); // 1
gen.next(); // 2

gen.prev(); // 2
gen.next(); // 2

gen.next(); // 3

Remaining and Length Counts

The remaining count is direction dependent.

var gen = R.iterate([ 1, 2, 3 ]);

gen.next();
gen.remaining(); // 2

gen.reverse();
gen.remaining(); // 1

gen.reverse();
gen.remaining(); // 2

This is in contrast to the length method, which always returns the actual length of the underlying data model.

var gen = R.iterate([ 1, 2, 3 ]);

gen.next();
gen.length(); // 3

gen.reverse();
gen.length(); // 3

gen.reverse();
gen.length(); // 3

The length is modified automatically by the push and pop methods.

Copyable Iterators

Iterator objects can be copied at any time. The copy will have the same state as the original.

var gen = R.iterate([ 1, 2, 3 ]);

gen.next(); // 1

var cpy = gen.copy();

cpy.next(); // 2
gen.next(); // 2

Each copy will have it's own model, so modifications to one will not affect the other.

Push and Pop

The push and pop methods allow us to modify the modet itself are indexed absolutely. Indexes are 1 based, as opposed to the standard 0 based indicies we are used to.

This was done for mathematical simplicity.

var gen = R.iterate([ 1, 2, 3 ]);

gen.push(1, [ 4 ]);
gen.data(); // [ 4, 1, 2, 3 ];

gen.next(); // 4
gen.pop(1); // [ 4 ]

Iterators can be created empty, then populated later.

var gen = R.iterate();

gen.push([ 1 ]);
gen.push([ 2, 3 ]);

gen.data(); // [ 1, 2, 3 ]

The pop method also may also be supplied with a count parameter to specify how many elements to remove.

var gen = R.iterate([ 1, 2, 3, 4 ]);

gen.next(); // 1
gen.next(); // 2

gen.pop(1, 2); // [ 1, 2 ]

gen.prev(); // undefined
gen.next(); // 3
gen.prev(); // 3

Data and Index

The underlying model and cursor index are available through the data and index methods.

var gen = R.iterate([ 1, 2, 3, 4 ]);

gen.data(); // [ 1, 2, 3, 4 ]

gen.next(); // 1
gen.next(); // 2

gen.index(); // 2

Transform and Generate

To generate the Fibonacci Sequence we could do something like the following.

var fib = R.iterate([ 0, 1 ]);

fib.transform(function(v, u) {
  this.push([ v + u(1) ]);
  return v;
});

fib.next(); // 0
fib.next(); // 1
fib.next(); // 1
fib.next(); // 2
fib.next(); // 3
fib.next(); // 5, and so on...

This allows us to quite concisely calculate the set of Fibonacci numbers up to the first one over 10,000.

var fib = R.iterate([ 0, 1 ]).transform(function(v, u) {
  this.push([ v + u(1) ]);
  return v;
});

while(fib.cursor(true) < 10000) {
  R.log(fib.next());
};

Passing a truthy value to the cursor method ensures that it returns a value, meaning it will be bumped off either end. This lets us initiate a while loop more simply.

Our previous implementation isn't very robust. What would happen if we were to traverse our iterator in reverse? We would be appending values to the end of our iterator and this is not what we want.

var fib = R.iterate([ 0, 1 ]);

fib.transform(function(v, u) {
  if( (this.direction() === 'forward') && !u(2) && u(1) ) {
    this.push([ v + u(1) ]);
  }
  return v;
});

This second version of our Fibonacci generator works as expected. We generate values when traversing forward, and only when we need them.

fib.next(); // 0
fib.next(); // 1
fib.next(); // 1
fib.next(); // 2
fib.next(); // 3

There is only one catch. Since we generate our values with the transform method, we always have more elements in the array than we actually need. In most cases, this shouldn't be a problem, but what if this is unacceptable for your implementation? You need the generate method, which is called when attempting to move off either end of the model. The value returned by the generate method will be added to the model before actually moving allowing us to create our values on the fly.

var fib = R.iterate([ 0, 1 ]);

fib.generate(function(u) {
  var n = u(-2) + u(-1);
  if(!isNaN(n)) { return n; }
});

Now we have a Fibonacci sequence generator from zero to infinity. Not too shabby, but it gets slightly better. As you'd probably expect, the tranform method will still be called on generated values.

fib.transform(function(v, u) {
  return Math.pow(2, v);
});

We can now generate and caches the Fibbonacci sequence only when we need to. When our generator returns a value from its next or prev functions, those values will be returned as powers of two.

fib.next(); //   1
fib.next(); //   2
fib.next(); //   2
fib.next(); //   4
fib.next(); //   8
fib.next(); //  32
fib.next(); // 256

At any point the generate and transform methods can be unset by providing a falsy value to either method.

Chaining Iterators

We can acomplish some pretty interesting things by chaining iterators.

var a = R.iterate([ 1, 2, 3 ]);
var b = R.iterate([ 4, 5, 6 ]);
var c = R.iterate([ 7, 8, 9 ]);

var chain = R.chain(a, b, c);

while(chain.remaining()) {
  R.log(chain.next());
});

Again, it's slightly better than just that. Chains actually call their component iterator's next method. This means their remaining count is consistent even when being incremented as part of a chain.

Reversal of iterators that are part of a chain is not yet handled.

var a = R.iterate([ 1, 2, 3 ]);
var b = R.iterate([ 4, 5, 6 ]);
var c = R.iterate([ 7, 8, 9 ]);

var chain = R.chain(a, b, c);

chain.next(); // 1
chain.next(); // 2

a.remaining(); // 1
b.remaining(); // 3

chain.next(); // 3
chain.next(); // 4

a.remaining(); // 0
b.remaining(); // 2

Conclusion

By using RaptorJuice's iteration techniques, we can flatten, and iterate over a presently indeterminate sequence of values.

When all is said and done, RaptorJuice implements more of a dequeue than an iterator, strictly speaking.