tuplejs

1.0.1 • Public • Published

TupleJS

Build Status

TupleJS is an open source pseudoclassical recursive tuple data structure library and npm module.

With TupleJS you can create tuple data structures, akin to an array and object chimera, with the ability to find values, modify values, delete elements, swap elements, rename element keys, add elements, and delete elements.

Usage

The npm module can be installed globally and saved in your current workspaces' dependencies via npm:

[sudo] npm install -g tuplejs --save

Development

Contributions are welcomed and encouraged.

Getting Started

Clone down the repo:

https://github.com/TupleJS/TupleJS.git

Install the required dependencies:

[sudo] npm install

Code Overview

Unless you know your implimentation using TupleJS will work, you should surround your calls to any of the TupleJS constructor or methods with try-catch blocks. Using bluebird to catch exceptions should make the process less tedious.

/dataStructure contains the tuple.js file which holds the pseudoclassical constructor and its methods, the errorFunctions.js file which holds the exceptions, and the helperFunctions.js file which holds some helper functions used in testing.

/test contains files for testing and more is available in the Testing section.

To create a new instance of a tuple, you must require the package first with:

var Tuple = require('TupleJS');

Constructor Usage

To instantiate your tuple, you can instantiate it with a call to the constructor passing in your tuple and some optional parameters.

Passing in a non-nested tuple:

var t = new Tuple(["blah", {two: 2}, 5]);

Passing in a nested tuple:

var t = new Tuple(["blah", {two: 2}, [5, {three: 3}]]);

The array argument as the first parameter to the Tuple constructor is how tuples are represented. Each entry is either a string, boolean, number, object, or array (another tuple). If the entry is an object, it represents a dictionary-like entry with a key and value. If no optional arguments are passing in then only the findLocation and findValue methods will work; otherwise calling the following methods will throw exceptions: modifyValue, deleteElement, swapElements, renameElementKey, addElement, addElements. Each of these methods have their own way of changing whether they can be called without throwing an exception or not with the exception of addElement/addElements who both rely on the "addElement" state.

Passing in an empty tuple with optional methods:

var t = new Tuple([],"modifyValue", true); //Sets the modifyValue's method state to true
var t = new Tuple([],"addElement"); //Toggles the addElement's method state
var t = new Tuple([],["addElement", "deleteElement"]); //Toggles the addElement and deleteElement's method state
var t = new Tuple([], {"addElement": true, "deleteElement": false, "findLocation": false}); //set's the addElement method state to true, set's the deleteElement method state to false, sets the findLocation method state to false

The constructor will throw a TupleInputError if the tuple is not an array, throw a ConstructorInputError if one of the elements in the tuple is not of the right format, but does not throw an error is no arguments are passed in. In that case an empty tuple is instantiated.

findValue

findValue method will return the value at an index or key and throws an error if it's not found. By default the ability to use the findValue method is turned on. findValue does not support method chaining.

var t = new Tuple(["blah", {two: 2}, 5]);
t.findValue(0); // "blah"
t.findValue(1); // 2
t.findValue(2); // 5
t.findValue('two'); // 2
t.findValue(5.5); // throws a KeyOrIndexError

modifyValue

modifyValue method will allow you to modify an elements value. By default the ability to use the modifyValue method is turned off. modifyValue does support method chaining.

var t = new Tuple(["blah", {two: 2}, 5], "modifyValue");
t.findValue(0); // "blah"
t.modifyValue(0,true);
t.findValue(0); // true
t.modifyValue("three",42); // throws a KeyOrIndexError
var t = new Tuple(["blah", {two: 2}, 5]);
t.findValue(0); // "blah"
t.modifyValue(0,true); // throws a StateError
t.modifyState("modifyValue");
t.findValue(0); // "blah"
t.modifyValue(0,true);
t.findValue(0); // true
t.modifyValue("three",42); // throws a KeyOrIndexError

renameElementKey

renameElementKey method will allow you to rename an elements' old key with a new key. By default the ability to use the renameElementKey method is turned off. renameElementKey does support method chaining.

var t = new Tuple(["blah", {two: 2}, 5], "renameElementKey");
t.findValue('two'); // 2
t.findValue('meow'); // throws a KeyOrIndexError
t.renameElementKey('two','meow');
t.findValue('two'); // throws a KeyOrIndexError
t.findValue('meow'); // 2
t.renameElementKey('meow',1); // throws a KeyError
t.renameElementKey(1,'kitty'); // throws a KeyError
t.renameElementKey('meow',true); // throws a KeyOrIndexError
t.renameElementKey('meow','meow'); // throws a KeyOrIndexError
var t = new Tuple(["blah", {two: 2}, 5]);
t.renameElementKey('two','meow'); // throws a StateError
t.modifyState("renameElementKey");
...

addElement

addElement method will allow you to add an element at a specific index or key. By default the ability to use the addElement method is turned off. addElement does support method chaining.

var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement('kitty'); // the tuple now is ["blah", {two: 2}, 5, "kitty"]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement('kitty',3); // the tuple now is ["blah", {two: 2}, 5, "kitty"]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement('kitty',1); // the tuple now is ["blah", "kitty", {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement('kitty',0); // the tuple now is ["kitty", "blah", {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement({billy: "bob"}); // the tuple now is ["blah", {two: 2}, 5, {billy: "bob"}]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement({billy: "bob"},3); // the tuple now is ["blah", {two: 2}, 5, {billy: "bob"}]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement({billy: "bob"},1); // the tuple now is ["blah", {billy: "bob"}, {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement({billy: "bob"},'two'); // the tuple now is ["blah", {billy: "bob"}, {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement({billy: "bob"},0); // the tuple now is [{billy: "bob"}, "blah", {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement({billy: "bob"},2.5); // the tuple now is ["blah", {two: 2}, 5] and throws an IndexError
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElement({billy: "bob"},'meow'); // the tuple now is ["blah", {two: 2}, 5] and throws a KeyOrIndexError
var t = new Tuple(["blah", {two: 2}, 5]);
t.addElement(42); // throws a StateError
t.modifyState("addElement");
...

addElements

addElements method will allow you to add multiple elements at a specific indicies or key's. By default the ability to use the addElements method is turned off. addElements does support method chaining.

var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElements([{"element": false},{"element": {kitty: "cute"}},{"element": 42}],3); // the tuple now is ["blah", {two: 2}, 5, false, {kitty: "cute"}, 42]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElements([{"element": false, "keyOrIndex": 3},{"element": {kitty: "cute"}, "keyOrIndex": 4},{"element": 42, "keyOrIndex": 5}]); // the tuple now is ["blah", {two: 2}, 5, false, {kitty: "cute"}, 42]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElements([{"element": false},{"element": {kitty: "cute"}},{"element": 42}],1); // the tuple now is ["blah", false, {kitty: "cute"}, 42, {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElements([{"element": false},{"element": {kitty: "cute"}},{"element": 42}],'two'); // the tuple now is ["blah", false, {kitty: "cute"}, 42, {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElements([{"element": false, "keyOrIndex": 'two'},{"element": {kitty: "cute"}, "keyOrIndex": 2},{"element": 42, "keyOrIndex": 3}]); // the tuple now is ["blah", false, {kitty: "cute"}, 42, {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElements([{"element": false},{"element": {kitty: "cute"}},{"element": 42}],0); // the tuple now is [false, {kitty: "cute"}, 42, "blah", {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElements([{"element": false, "keyOrIndex": 0},{"element": {kitty: "cute"}, "keyOrIndex": 1},{"element": 42, "keyOrIndex": 2}]); // the tuple now is [false, {kitty: "cute"}, 42, "blah", {two: 2}, 5]
var t = new Tuple(["blah", {two: 2}, 5], "addElement");
t.addElements({billy: "bob"}); // the tuple now is ["blah", {two: 2}, 5] and throws an ArrayError

deleteElement

deleteElement method will allow you to delete elements at a specific indicies or key's. By default the ability to use the deleteElement method is turned off. deleteElement does support method chaining.

var t = new Tuple(["blah", {two: 2}, 5], "deleteElement");
t.deleteElement(0); // the tuple now is [{two: 2}, 5]
t.deleteElement('two'); // the tuple now is [5]
t.deleteElement(0); // the tuple now is []
var t = new Tuple(["blah", {two: 2}, 5]);
t.deleteElement(0); // throws a StateError error
t.modifyState("deleteElement");
t.deleteElement(2); // the tuple now is ["blah", {two: 2}]
t.deleteElement(2); // throws a KeyOrIndexError error
t.deleteElement(1); // the tuple now is ["blah"]
t.deleteElement('two'); // throws a KeyOrIndexError error
t.deleteElement(0); // the tuple now is []

swapElements

swapElements method will allow you to swap elements at a specific indicies or key's. By default the ability to use the swapElements method is turned off. swapElements does support method chaining.

var t = new Tuple(["blah", {two: true}, {three: 7}, 5], "swapElements");
t.swapElements(0,3); // [5, {two: true}, {three: 7}, "blah"]
t.swapElements('two','three'); // [5, {three: 7}, {two: true}, "blah"]
t.swapElements(1,'two'); // [5, {two: true}, {three: 7}, "blah"]
t.swapElements('two',2); // [5, {three: 7}, {two: true}, "blah"]
var t = new Tuple(["blah", {two: true}, {three: 7}, 5], "swapElements");
t.swapElements(10,11); // the tuple is still ["blah", {two: true}, {three: 7}, 5] but throws a KeyOrIndexError error
t.swapElements(1,'ten'); // the tuple is still ["blah", {two: true}, {three: 7}, 5] but throws a KeyOrIndexError error

inputTuple

inputTuple method will output the current state of the tuple as input to a new Tuple constructor. The ability to use the inputTuple method is always on. inputTuple does support method chaining with the correct arguments.

var t = new Tuple(["blah", {two: 2}, 5]);
t.inputTuple(); // returns an array and does not support method chaining: ["blah", {two: 2}, 5]
t.inputTuple("print"); // prints out the following and does support method chaining: here is the tuple in its current state as a string which can be used to instantiate a new tuple: ["blah", {two: 2}, 5]

internalTuple

internalTuple method will output the current state of the tuple as represented internally. The ability to use the internalTuple method is always on. internalTuple does support method chaining with the correct arguments.

var t = new Tuple(["blah", {two: 2}, 5]);
t.internalTuple(); // returns an object and does not support method chaining: 
  { '0': { val: 'blah' },
    '1': { val: 2, key: 'two' },
    '2': { val: 5 },
    two: { val: 2, key: 1 } }
t.internalTuple("print"); // prints out the following and does support method chaining: here is the tuple in its current state as a string which can be used to instantiate a new tuple: 
  { '0': { val: 'blah' },
    '1': { val: 2, key: 'two' },
    '2': { val: 5 },
    two: { val: 2, key: 1 } }

len

len method will allow you to figure out the length of the current tuple but not the length of any nested tuples, you need to manually select those using findValue. The ability to use the len method is always on. len does not support method chaining.

var t = new Tuple();
t.len(); // 0
var t = new Tuple([]);
t.len(); // 0
var t = new Tuple(["blah", {two: 2}, 5]);
t.len(); // 3

getState

getState method returns the current state of the method's allowed to be executed. The ability to use the getState method is always on. getState does not support method chaining.

var t = new Tuple(["blah", {two: 2}, 5]);
t.getState(); // returns: 
  { findLocation: true,
    findValue: true,
    modifyValue: false,
    deleteElement: false,
    swapElements: false,
    renameElementKey: false,
    addElement: false }
t.modifyState("swapElements");
t.getState(); // returns: 
  { findLocation: true,
    findValue: true,
    modifyValue: false,
    deleteElement: false,
    swapElements: true,
    renameElementKey: false,
    addElement: false }

modifyState

modifyState method modifies the current state of the method's allowed to be executed. The ability to use the modifyState method is always on. modifyState does support method chaining.

var t = new Tuple();
t.modifyState("modifyValue", true); //Sets the modifyValue's method state to true
var t = new Tuple();
t.modifyState("addElement"); //Sets the addElement's method state to true
var t = new Tuple();
t.modifyState(["addElement", "deleteElement"]); //Toggles the addElement and deleteElement's method state
var t = new Tuple();
t.modifyState({"addElement": true, "deleteElement": false, "findLocation": false}); //set's the addElement method state to true, set's the deleteElement method state to false, sets the findLocation method state to false
var t = new Tuple();
t.modifyState("someMethod"); // throws an InputError error
var t = new Tuple();
t.modifyState(true); // throws an ModifyStateError error, the first argument must be a string

Testing

The nature of this project requires extensive tests, which are located in /test

To run the test suite:

grunt test

The test suite contains tests for testing a single aspect of TupleJS, the non-nested tuple forms, and nested tuple forms.

  • Simple tests ensure the non-nested instances of a tuple run correctly

  • Nested tests ensure the nested instances of a tuple run correctly

To run any of these particular tests, rather then the entire test suite, use one of the following, respectively:

grunt simple

grunt nested

Tests should remain marked as pending until they pass, otherwise Travis CI will fail.

Contributing

  1. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug.

  2. Fork the TupleJS repository on Github to start making your changes. Cut a namespaced feature branch from master that is named appropriately for the feature you plan to work on.

  3. Tests are very important for this project. Write tests that show the bug was fixed or that the feature works as expected.

  4. Send a pull request.

More details can be found at the contribution guide: CONTRIBUTING.

Current Version

npm package information

License

MIT License

Author Information

TupleJS was created by Max Yazhbin.

Package Sidebar

Install

npm i tuplejs

Weekly Downloads

0

Version

1.0.1

License

MIT

Last publish

Collaborators

  • myazhbin