Giter Club home page Giter Club logo

101's Introduction

101

NPM

Build Status Coverage Status Dependency Status devDependency Status

Why another JS util library?

1) 101 will be maintained to minimize overlap with vanilla JS.

  • 101 utils are made to work well with vanilla JS methods.
  • 101 will only duplicate vanilla JS to provide Functional Programming paradigms, or if the method is not available in a widely supported JS version (currently ES5).
  • Other libraries often duplicate a lot of ES5: forEach, map, reduce, filter, sort, and more.

2) No need for custom builds.

  • With 101, import naturally, and what you use will be bundled.
  • Each util method is a module that can be required require('101/<util>').
  • Currently CommonJS (node, browserify, webpack, etc) is supported, I will add other module system support on request.
  • Other libraries can be large, and require manually creating custom builds when optimizing for size.

Why not release each as individual modules?

I usually agree with this philosophy; however, while in practice, adherence to the module-pattern can become quite annoying for micro-modules (like those in 101):

  • Micro-modules existance throughout a project can change very frequently, because of this one may find themselves constantly updating their package.json (repeatedly adding and removing the same micro-modules).
  • Unbundling micro-modules can lead to projects with hundreds of dependencies which can be tedious to maintain.

Installation

npm install 101

Usage

assign (aka extend)

Just like ES6's Object.assign. Extend an object with any number of objects (returns original).

var assign = require('101/assign');

var target = { foo: 1 };
var source1 = { bar: 1 };
var source2 = { baz: 1 };
assign(target, source1) // { foo: 1, bar: 1, baz: 1 } target extended with source objects
assign(target, source1, source2) // { foo: 1, bar: 1, baz: 1 } target extended with source objects

and

Functional version of &&. Works great with array.reduce.

var and = require('101/and');

and(true, false); // false
and(true, true);  // true
and(true, "foo");  // "foo"

apply

Functional version of function.apply. Supports partial functionality (great with array functions).

var apply = require('101/apply');
[sum].map(apply(null, [1, 2, 3])); // [6] = [sum(1,2,3)] = [1+2+3]
function sum () {  /* sums all arguments */ }
apply({ prop: 'val' })(function () { return this.prop; });  // 'val'

bindAll

Bind methods in an object. You can pass an array containing the name of the methods to bind as second argument or leave it empty to bind all the available methods.

var bindAll = require('101/bind-all');
var obj = {
  init: function() {
    this.on(this.handler);
  },
  on: function(handler) {
    return handler();
  },
  handler: function() {
    console.log(this.msg);
  },
  msg: 'Hello World'
}

obj.init(); // undefined

bindAll(obj);
obj.init(); // "Hello World"

bindAll(obj, ['handler']);
obj.init(); // "Hello World"

clone

It's clone (Only exporting this bc it is used internal to 101)

var clone = require('101/clone');
var obj = {
  foo: 1,
  bar: 2
};

clone(obj); // { foo: 1, bar: 2 }

compose

Functional composition method. Works great with array.reduce.

var compose = require('101/compose');

compose(isNaN, parseInt)('nope'); // isNaN(parseInt('nope')) // true

converge

Converges an array of functions into one. Works great with compose.

var converge = require('101/converge');

converge(mul, [add, sub])(6, 2); // mul(add(6, 2), sub(6, 2)) // (6+2) * (6-2) = 36

[ {a: true, b: false}
, {a: false, b: false}
, {a: true, b: true}
].filter(converge(and , [pluck("a") , pluck("b")])); // [{a: true, b: true}]

[f, converge(g, [h, i]), j].reduce(compose); // f(g(h(j), i(j)))

curry

Returns a curried function.

var curry = require('101/curry');

function add(a, b) { return a + b; }

var curriedAdd = curry(add);
var add2 = curriedAdd(2);

add2(6); // 8
add2(8); // 10

function join() { return Array.prototype.slice.call(arguments).join(''); }

curry(join, 3)(1)(0)(1); // "101"

defaults

Fill non-existing object values with defaults. Use it to set defaults on options. Works with supplying default values in sub-objects as well. Supports partial functionality (great with array functions). Mutates first argument and returns mutated argument.

var defaults = require('101/defaults');
var opts = { foo: 0, bar: 1 };
var defs = { foo: 1, bar: 2, qux: 2 };

defaults(opts, defs); // returns mutated `opts` { foo: 0, bar: 1, qux: 2 }
[opts].map(defaults(defs)); // [ { foo: 0, bar: 1, qux: 2 } ]

var opts = {
  foo: {
    one: 1,
    two: 2
  }
};
var defs = {
  foo: {
    two: 20,
    three: 30
  }
};
defaults(opts, defs); // { foo: { one: 1, two: 2, three: 30 } }

del

Functional version of delete obj[key] which returns the same obj without the deleted key. Supports partial functionality (great with array functions, like map).

var del = require('101/del');
var obj = {
  foo: 1,
  bar: 2
};

del(obj, 'foo'); // { bar: 2 }

// use it with array.map
[obj, obj, obj].map(del('foo')); // [{ bar: 2 }, {same}, {same}]

// supports keypaths by default
var obj = {
  foo: {
    moo: 1,
    boo: 2
  },
  bar: 3
};

del(obj, 'foo.moo'); // { foo: { boo: 2 }, bar:3 }

// pass an array of keys to be deleted 
del(obj, ['foo.moo', 'bar']) // { foo: { boo: 2 } }

envIs

Functional version of str === process.env.NODE_ENV. Or's multiple environments.

var envIs = require('101/env-is');
// process.env.NODE_ENV = development
envIs('development');     // true
envIs('production');      // false
envIs('staging', 'production');     // false
envIs('development', 'production'); // true

equals

Functional implementation of Object.is with polyfill for browsers without implementations of Object.is Supports partial functionality (great with array functions).

var equals = require('101/equals');

equals(1, 1);            // true
[1,2,3].some(equals(1)); // true
equals(1, '1');          // false

exists

Simple exists function.

var exists = require('101/exists');

exists('foo');     // true
exists(null);      // false
exists(undefined); // false

find

Just like ES6's array.find.

Finds the first value in the list that passes the given function (predicate) and returns it. If list is not provided find will return a partial-function which accepts a list as the first argument.

var find = require('101/find');
var hasProps = require('101/has-properties');
var arr = [{ a: 1, b: 1 }, { b: 1 }, { c: 1 }];

var item = find(arr, hasProps({ a:1 }));
// returns { a: 1, b: 1 }
// returns null if not found

// partial-function
var partial = find(hasProps({ a: 1 }));
var item = partial(arr);
// returns { a: 1, b: 1 }
// returns null if not found

findIndex

Just like ES6's array.findIndex.

Finds the first value in the list that passes the given function (predicate) and returns it's index. If list is not provided findIndex will return a partial-function which accepts a list as the first argument.

var findIndex = require('101/find-index');
var arr = [1, 2, 3];

var index = findIndex(arr, function (val, i, arr) {
  return val === 2;
});
// returns 1
// returns -1 if not found

flip

Returns a function with flipped arguments

var flip = require('101/flip');
var curry = require('101/curry');
var hasKeypaths = require('101/has-keypaths');

var hasFooBar = curry(flip(hasKeypaths))(['foo.bar']);

hasFooBar({ foo: { bar : true } }); // true


function prefix(pre, str) {
  return pre + str;
}

flip(prefix)('hello', '_'); // "_hello"

groupBy

Hashes an array into groups based on the value of a provided common key. Works nicely with pluck and reduce.

var groupBy = require('101/group-by');
var arr = [
    {id: 1, foo: 'bar'},
    {id: 2, foo: 'qux'},
    {id: 3, foo: 'qux'}
];

groupBy(arr, 'foo')
/*
{
  bar: [
    {id: 1, foo: 'bar'}
  ],
  qux: [
    {id: 2, foo: 'qux'},
    {id: 3, foo: 'qux'}
  ]
}
*/
// always provide initial value when using with reduce!
arr.reduce(groupBy('foo'), {}) // assumes pluck if passed string
arr.reduce(groupBy(pluck('foo')), {}) // also accepts function
/*
{
  bar: [
    {id: 1, foo: 'bar'}
  ],
  qux: [
    {id: 2, foo: 'qux'},
    {id: 3, foo: 'qux'}
  ]
}
*/

hasKeypaths

Determines whether the keypaths exist and have the specified values. Supports partial functionality (great with array functions, and 101/find).

var hasKeypaths = require('101/has-keypaths');
var obj = {
  foo: {
    bar: {
      qux: 1
    }
  }
};

hasKeypaths(obj, ['foo.bar.qux']);      // true
hasKeypaths(obj, { 'foo.bar.qux': 1 }); // true
hasKeypaths(obj, ['foo.qux']);          // false
hasKeypaths(obj, { 'foo.bar': 2 });     // false
hasKeypaths(obj, { 'foo.bar': 1, 'nope': 1 }); // false

// optional 'deep' arg, defaults to true
var barObj = { bar: 1 };
hasKeypaths(obj, { 'foo.bar': barObj });         // true
hasKeypaths(obj, { 'foo.bar': barObj }, true);   // true
hasKeypaths(obj, { 'foo.bar': barObj }, false);  // false
hasKeypaths(obj, { 'foo.bar': obj.foo }, false); // true
hasKeypaths(obj, ['foo.bar'], false);            // true, uses [hasOwnProperty vs in](http://stackoverflow.com/questions/13632999/if-key-in-object-or-ifobject-hasownpropertykey)

// use it with find, findIndex, or filter!
var arr = [obj, { b: 1 }, { c: 1 }];
find(arr, hasKeypaths({ 'foo.bar.qux':1 })); // { foo: { bar: { qux: 1 } } }
find(arr, hasKeypaths(['foo.bar.qux']));     // { foo: { bar: { qux: 1 } } }

// use it to verify options object has required properties
var opts = {
  host: 'localhost',
  port: '3333',
  user: {
    id: 5
  }
};
hasKeypaths(opts, ['host', 'port', 'user.id']); // true

hasProperties

Determines whether the keys exist and, if specified, has the values. Supports partial functionality (great with array functions, and 101/find). NOTE: I am considering deprecating this method, bc it is so similar to has-keypaths.

var hasProps = require('101/has-properties');
var obj = {
  qux: 1
};
obj['foo.bar'] = 1

hasProps(obj, ['foo', 'qux']); // true
hasProps(obj, { qux: 1 }) // true

// optional 'deep' arg, defaults to true
var barObj = { bar: 1 };
hasProps(obj, { 'foo.bar': barObj });         // true
hasProps(obj, { 'foo.bar': barObj }, true);   // true
hasProps(obj, { 'foo.bar': barObj }, false);  // false
hasProps(obj, ['foo.bar'], false);            // true, uses [hasOwnProperty vs in](http://stackoverflow.com/questions/13632999/if-key-in-object-or-ifobject-hasownpropertykey)
// use it with find, findIndex, or filter!
var arr = [{ a: 1, b: 1 }, { b: 1 }, { c: 1 }];
find(arr, hasProps({ a:1 })); // { a: 1, b: 1 }
find(arr, hasProps(['a']));   // { a: 1, b: 1 }

includes

Polyfill of ES7 proposed Array.prototype.includes. Will default to Array.prototype.includes if present.

var includes = require('101/includes');
var haystack = ['a', 'b', 'c', 'd', 'e'];
includes(haystack, 'c'); // true

// optional 3rd argument, searchFrom. Begin searching the target array from a specified index.
includes(haystack, 'c', 3); // false
includes(haystack, 'c', 0); // true

// partial argument functionality
var i = includes(haystack);
i('c') // true
i('g') // false

// example composition usage:
var not = require('101/not');
var notIn = not(includes);
[1, 2, 3, 4, 5].filter(notIn([1, 2, 3])); // [4, 5]

indexBy

Hashes an array of objects based on the value of a provided common key. Works nicely with pluck and reduce.

var arr = [
  {foo: 'bar'},
  {foo: 'qux'}
];

arr.reduce(indexBy('foo'), {}) // assumes pluck if passed string
arr.reduce(indexBy(pluck('foo')), {}) // also accepts function
// {bar: {foo: 'bar'}, qux: {foo: 'qux'}}
// always provide initial value when using with reduce!
arr.reduce(indexBy(pluck('foo')), {}) // {bar: {foo: 'bar'}, qux: {foo: 'qux'}}

instanceOf

Functional version of JavaScript's instanceof. Supports partial functionality (great with array functions).

var instanceOf = require('101/instance-of');

['foo', 'bar', 1].map(instanceOf('string')); // [true, true, false]

isBoolean

Functional version of typeof val === 'boolean'. Supports partial functionality (great with array functions).

var isBoolean = require('101/is-boolean');

[true, false, 1].map(isBoolean); // [true, true, false]

isEmpty

Functional version of val empty object, array or object

var isEmpty = require('101/is-empty');

isEmpty([]); // true
isEmpty({}); // true
isEmpty(""); // true
isEmpty(" "); // false

isFunction

Functional version of typeof val === 'function'

var isFunction = require('101/is-function');

[parseInt, function () {}, 'foo'].map(isFunction); // [true, true, false]

isInteger

Check if a value is an instance of an integer.

var isInteger = require('101/is-Integer');

isInteger(101); // true
isInteger(101.01); // false

isNumber

Functional version of val typeof 'number'.

var isNumber = require('101/is-number');

['foo', NaN, 1].map(isNumber); // [false, false, true]

isObject

Functional strict version of val typeof 'object' (and not array or regexp)

var isObject = require('101/is-object');

[{}, { foo: 1 }, 100].map(isObject); // [true, true, false]

isRegExp

Check if a value is an instance of RegExp

var isRegExp = require('101/is-regexp');

[new RegExp('.*'), /.*/, {}, 1].map(isRegExp); // [true, true, false, false]

isString

Functional version of val typeof 'string'

var isString = require('101/is-string');

['foo', 'bar', 1].map(isString); // [true, true, false]

keysIn

Return an array containing all the keys of an object. It differs from the native Object.keys by including also the prototype keys.

var keysIn = require('101/keys-in');
var User = function() {
  this.msg = 'Hello World';
}
User.prototype.isLoggedIn = function() { /* example function */ }

var user = new User();
keysIn(user); // ['msg', 'isLoggedIn']

last

Returns the last value of a list

var last = require('101/last');

last([1, 2, 3]); // 3
last('hello');   // 'o'

lens

Create a lens to access a data structure. When passed a property key as a string, it returns a function fn(obj) that acts as a getter for that. It also exposes .set(value, obj) and .mod(fn, obj).

var fooLens = lens('foo');
var toUpper = function(str) { return str.toUpperCase(); };
var obj = {
  foo: 'foo',
  bar: 'bar'
};

fooLens(obj); // => 'foo'
fooLens.set('moo', obj); // => { foo: 'moo', bar: 'bar' }
fooLens.mod(toUpper, obj); // => { foo: 'MOO', bar: 'bar' }

You may also provide getter and setter functions.

var arr = ['foo', 'bar'];
var first = lens(
    function(arr) { return arr[0]; },
    function(val, arr) { var clone = arr.slice(); clone[0] = val; return clone; }
);

first(arr); // => 'foo'
first.set('moo')(arr); // => ['moo', 'bar']
first.mod(toUpper)(arr); // => ['FOO', 'bar']

noop

No-op function

require('101/noop'); // function () {}

not

Functional version of !.

var not = require('101/not');

not(isString)('hey'); // false
not(isString)(100);   // true

omit

Immutable version of delete obj.key. Returns a new object without the specified keys. Supports partial functionality (great with array functions, like map).

var omit = require('101/omit');
var obj = {
  foo: 1,
  bar: 2
};

omit(obj, 'foo');          // { bar: 1 }
omit(obj, ['foo']);        // { bar: 1 }
omit(obj, ['foo', 'bar']); // { }

// use it with array.map
[obj, obj, obj].map(omit('foo')); // [{ bar: 1 }, { bar: 1 }, { bar: 1 }];

or

Functional version of ||. Works great with array.reduce.

var or = require('101/or');

or(true, true);   // true
or(true, false);  // true
or(false, false); // false
or("foo", false); // "foo"

passAll

Muxes arguments across many functions and &&'s the results. Supports partial functionality (great with array functions, like map).

var passAll = require('101/pass-all');

['', 'foo', 'bar', 100].map(passAll(isString, isTruthy)); // [false, true, true, false]

passAny

Muxes arguments across many functions and ||'s the results. Supports partial functionality (great with array functions, like map).

var passAny = require('101/pass-any');

['', 'foo', 'bar', 100].map(passAny(isString, isNumber)); // [true, true, true, true]

pick

Returns a new object with the specified keys (with key values from obj). Supports regular expressions and partial functionality (great with array functions, like map).

var pick = require('101/pick');
var obj = {
  foo: 1,
  bar: 2,
  qwk: {
    wrk: 1
  },
  'qwk.wrk': 2
};

pick(obj, 'foo');          // { foo: 1 }
pick(obj, RegExp('oo$'));  // { foo: 1 }
pick(obj, ['foo']);        // { foo: 1 }
pick(obj, ['foo', 'bar']); // { foo: 1, bar: 2 }

// use it with array.map
[obj, obj, obj].map(pick('foo')); // [{ foo: 1 }, { foo: 1 }, { foo: 1 }];

// supports keypaths
pick(obj, 'qwk.wrk');      // { qwk: { wrk: 1 } }
pick(obj, '["qwk.wrk"]');  // { 'qwk.wrk': 2 } }

pluck

Functional version of obj[key], returns the value of the key from obj. Supports partial functionality (great with array functions, like map).

var pluck = require('101/pluck');
var obj = {
  foo: 1,
  bar: 2
};

pluck(obj, 'foo'); // 1

// use it with array.map
[obj, obj, obj].map(pluck('foo')); // [1, 1, 1]

// supports keypaths by default
var obj = {
  foo: {
    bar: 1
  },
  'foo.bar': 2
};

pluck(obj, 'foo.bar'); // 1, supports keypaths by default
pluck(obj, 'foo.bar', false); // 2, pass false to not use keypaths

put

Immutable version of obj[key] = val. Returns a clone of the obj with the value put at the key. Supports partial functionality (great with array functions, like map).

var put = require('101/put');
var obj = {
  foo: 1,
  bar: 2
};

put(obj, 'baz', 3); // { foo: 1, bar:2, baz: 3 }
obj; // { foo: 1, bar: 2 } (not modified)

// use it with array.map
[obj, obj, obj].map(put('foo', 100)); // [{ foo: 100, bar: 2 }, {copy}, {copy}]
obj; // { foo: 1, bar: 2 } (not modified)

// supports keypaths by default
var obj = {
  bar: 2
};

put(obj, 'foo.qux', 100); // { foo: { qux: 100 }, bar: 2 }
put(obj, {
  'foo.qux': 100
  'yolo': 1
}); // { foo: { qux: 100 }, bar: 2, yolo: 1 }
obj; // { foo: 1, bar: 2 } (not modified)

set

Functional version of obj[key] = val, returns the same obj with the key and value set. Supports partial functionality (great with array functions, like map).

var set = require('101/set');
var obj = {
  foo: 1,
  bar: 2
};

set(obj, 'foo'); // 1

// use it with array.map
[obj, obj, obj].map(set('foo', 100)); // [{ foo: 100, bar: 2 }, {same}, {same}]

// supports keypaths by default
var obj = {
  bar: 2
};

set(obj, 'foo.qux', 100); // { foo: { qux: 100 }, bar: 2 }
set(obj, {
  'foo.qux': 100
  'yolo': 1
}); // { foo: { qux: 100 }, bar: 2, yolo: 1 }

values

Returns Array containing the values of the properties of an object

var values = require('101/values');
var obj {
  foo: 'apple',
  bar: 'orange'
};

var objValues = values(obj);
objValues // ['apple', 'orange']

xor

Exclusive or Works great with array.reduce.

var xor = require('101/xor');

xor(true, true);   // false
xor(true, false);  // true
xor(false, true);  // true
xor(false, false); // false

License

MIT

101's People

Contributors

albertorestifo avatar bkendall avatar cflynn07 avatar duncanbeevers avatar erayarslan avatar jabez128 avatar jakehp avatar jfsiii avatar jrf0110 avatar mitogh avatar richardlitt avatar rstacruz avatar ryun avatar srph avatar stoeffel avatar tjmehta avatar tmcw avatar tristaaan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

101's Issues

add includes

includes([1,2,3,4], 1) // true
var notIn = not(includes);
[1,2,3,4,5].filter(notIn([1,2,3])) // [4,5]

remove

remove([1,2,3], 1)
remove([1,2,3], equals(1))

tail

With #87 101 will have a first function which often comes with a tail function.

tail([1, 2, 3, 4]);
// => [2, 3, 4]

tail('_hello');
// => 'hello'

🌻

proposal: indexBy

Should it work with reduce?

[ 
  { foo: 'bar', bar: 'yo' }, 
  { foo: 'qux' }, 
  { foo: 'flux' }, 
  { foo: 100 }
].reduce(indexBy('foo'), {});
/* returns 
{
  'bar': { foo: 'bar', bar: 'yo' },
  'foo':  { foo: 'qux' }, 
  'flux': { foo: 'flux' },
  '100': { foo: 100 }
}
*/

Note: It requires an initial value which makes it a less "plug and play".

Or just

indexBy(arr, 'foo')

101/defaults should either mutate the `target` argument or clone and return an extended object, not both

101/defaults currently both mutates it's target argument and returns the mutated target argument. This isn't shown in the documentation. https://github.com/tjmehta/101#defaults

It should either:

  1. clone target, extend target, and return target
    or
  2. extend target and return undefined (or maybe return a boolean indicating if defaults were applied or not)

Mutating the argument and returning it is redundant.

Edit:
Came across this use of defaults in our code:

// unnecessary to assign return value to opts, implementor was unaware defaults mutates and returns
opts = defaults(opts, { foo: 'bar' });

composed function takes only one argument

Currently a composed function takes only one argument:

function compose(f,g) {
  return function composed(x) { 
    return f(g(x));
  } 

With this implementation you can't do this:

var add = function(a, b) { return a+b; };
var sqr = function(a) { return a*a; };

var composed = compose(sqr, add);
composed(1, 2);
// expected => 9
// actual => NaN

How about we change compose to create a function which passes all arguments to the first function:

function compose(f,g) {
  return function composed(/* args */) { 
    var args = Array.prototype.slice.call(arguments);

    return f(g.apply(null, args));
  } 

Checkout my implementation of compose it passes all arguments to the first function (https://github.com/stoeffel/compose-function)

groupBy

Should it work with reduce?

[ 
  { foo: 'bar', bar: 'yo' }, 
  { foo: 'bar' }, 
  { foo: 'flux' }, 
  { foo: 'flux', qux: 100 }
].reduce(groupBy('foo'), {});
/* returns 
{
  'bar': [
    { foo: 'bar', bar: 'yo' },
    { foo: 'bar' }
  ],
  'flux': [
    { foo: 'flux' }, 
    { foo: 'flux', qux: 100 }
  ]
}
*/

Note: It requires an initial value which makes it a less "plug and play".

Or just

groupBy(arr, 'foo')

Add a "compose" function

Great library. "compose" would be good. Maybe "pipe" too so that you send values through a series of functions.

Returning module exports

This isn't an issue, just a question:

@tjmehta Is there any reason you're returning module exports like this?

module.exports = and;

function and (a, b) {
  return a && b;
}

Why not this?

module.exports = function(a, b) {
  return a && b;
}

or this?

function and (a, b) {
  return a && b;
}

module.exports = and;

or this?

var and = function (a, b) {
  return a && b;
}

module.exports = and;

or this?

module.exports = and;

var and = function (a, b) {
  return a && b;
}

I'm not trying to sound snobby or anything. I know people have many different preferred ways of doing things. I was just wondering if there was a specific reason for doing so. It seems weird to use the function before it's called. I'm very curious! Thanks!

matches

thoughts: accept an object that takes keypaths and regexp values too.

SortBy

arr.sort(sortBy('key.path')) or arr.sort(sortBy('-key.path'))

Last does not guarantee the last element

This is a bug I came across in a project.

I implemented my own .last() method, then. I realized the problem is, using Object.keys() method returns different array for different browser. Generally browsers tend to return the order as the indexes inserted by it's better not to trust it.

Maybe it's better to sort alphabetically and return the last result here

Detailed explanation is on stackoverflow

better error message for clone errors

methods that use clone can cause it to throw errors.
these error message are not developer friendly (stack traces pointing to clone code)
throw more better errors in these scenarios so that the error can be trace to the 101 method being used.

unique

to get unique values in an array

  1. make it work with arr.reduce
  2. maybe accept an an optional equals arg?

Publishing functions as single modules

First, I know this is against one of the philosophies of 101. But as the library grows it would sometimes be nice if one could install only what he needs. i.e npm i 101-curry. We could create a cli-tool to publish only changed function and keep developing 101 in one repo.
What are your thoughts on this?

Additional checkings

Hi! Very nice lib, I like the way it is included.
Im't thinking to replace mutype with 101 in all depending projects, but 101 still lacks of some, I believe, useful checks:

  • has(obj, property) — a faster check than .hasOwnProperty (http://jsperf.com/hasownproperty-vs-in-vs-undefined/12).
  • isNumber — to avoid typeof a === 'number' (useful for closurecompiler).
  • isPlain!arg || isBoolean(arg) || isNumber(arg) || isString(arg) — very often needed to exclude non-objects.
  • isArrayLike / isList — to check anything which looks like an ordered collection Array, NodeList, Collection, or anything with numeric length but not string, window, form, function.
  • isArray, isRegExp
  • isEmpty — whether object is empty.

Could `set` accept a function?

Is it possible to bend set to set properties through a function? I mean like:

var markdown = require("marked");

[{string: "..."}, {string: "..."}].map(compose
  ( set("html", markdown)
  , pluck("string")
  ));

Infinite Compose

It's be awesome if compose took an unlimited amount of arguments. Is there a reason this is not the case? (Could help out with a PR if no one objects) @tjmehta

$ node
> var compose = require('101/compose')
undefined
> var plusOne = (x) => x + 1
undefined
> compose(plusOne, plusOne, plusOne)(1)
3
> compose(plusOne, plusOne, plusOne, plusOne)(1)
3

proposal: bindAll

Yes, yes, the native Function.prototype.bind method is solid, but there are situations where the Underscore bindAll method is just what you need.

I propose to extract the bindAll method from the Underscore library, remove the support for when the ES5 bind is not available and call it a day.

If there is enough interest, I can create a PR

omit perf

omit currently clones the source object and then deletes "omitted" properties from the copy.
In the scenario that omitted properties are very large, clone is unnecessarily copying a large amount of data and immediately deleting it.

Reimplement omit to avoid copying "omitted" properties.

Consider building as ES6 modules.

Why

You've reached a conclusion in #17, that AMD is fairly compatible with CommonJS – you can use one within the other or transpile one to the other. That's not the case with ES6 modules. They are designed to be statically analysable (without executing the code) – so there are things impossible to transpile. Such as:

if (hasToGo) require('car').driveHome();
// ...or:
module.exports = something || somethingElse;
How

Looking by the simplicity of your modules, it should be easy to copy each file to 101/es6/, replacing:

  • module.exports = a; with export default a;, and
  • var b = require('./b'); with import b from './b';.

I've had a very rough go at this, because I needed two modules in an ES6 project. A simple search-and-replace did it in my case: tomekwi/101-es6.

The only problem

The problem is dependency on CommonJS modules (clone, keypather and deep-eql – we should be able to replace extend with 101/assign).

Possible solutions:

  1. Implement these ourselves (I guess it can be out of the question at the moment)
  2. Compile only non-dependent modules to ES6
  3. Compile everything as-it-is (just import clone from 'clone';). Some compilers (6to5) can handle this as a temporary ES5-ES6 brigde.

breaks npm v3.3.5/3.3.6 outdated cmd when listed as a devDependency in package.json

Pretty crazy issue. My npm outdated started failing... After some tracing I noticed that 101 causes a weird run in the dependency array built in the npm outdated utility. I'm guessing this is a npm bug related to the numeric module name (tests with "202" and "2" showed the same result).

Documenting here, in case you want to raise an issue with the npm team. A brief search makes me think this hasn't been filed yet.

Steps to reproduce:

  • add any module with a numeric name to the devDependencies object in package.json
  • run npm outdated
  • receive error like below
npm ERR! Darwin 15.0.0
npm ERR! argv "/usr/local/Cellar/node/4.2.1/bin/node" "/Users/mshick/.node/bin/npm" "outdated"
npm ERR! node v4.2.1
npm ERR! npm  v3.3.6

npm ERR! Cannot read property 'name' of undefined

Here's a sample npm-debug.log entry:

0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/Cellar/node/4.2.1/bin/node',
1 verbose cli   '/Users/mshick/.node/bin/npm',
1 verbose cli   'outdated' ]
2 info using [email protected]
3 info using [email protected]
4 silly mapToRegistry name MD5
5 silly mapToRegistry using default registry
6 silly mapToRegistry registry https://registry.npmjs.org/
7 silly mapToRegistry uri https://registry.npmjs.org/MD5
8 silly mapToRegistry name adm-zip
9 silly mapToRegistry using default registry
10 silly mapToRegistry registry https://registry.npmjs.org/
11 silly mapToRegistry uri https://registry.npmjs.org/adm-zip
12 verbose stack TypeError: Cannot read property 'name' of undefined
12 verbose stack     at /Users/mshick/.node/lib/node_modules/npm/lib/outdated.js:295:27
12 verbose stack     at /Users/mshick/.node/lib/node_modules/npm/node_modules/slide/lib/async-map.js:52:35
12 verbose stack     at Array.forEach (native)
12 verbose stack     at /Users/mshick/.node/lib/node_modules/npm/node_modules/slide/lib/async-map.js:52:11
12 verbose stack     at Array.forEach (native)
12 verbose stack     at asyncMap (/Users/mshick/.node/lib/node_modules/npm/node_modules/slide/lib/async-map.js:51:8)
12 verbose stack     at outdated_ (/Users/mshick/.node/lib/node_modules/npm/lib/outdated.js:294:3)
12 verbose stack     at /Users/mshick/.node/lib/node_modules/npm/lib/outdated.js:78:5
12 verbose stack     at /Users/mshick/.node/lib/node_modules/npm/lib/install/deps.js:119:5
12 verbose stack     at LOOP (/Users/mshick/.node/lib/node_modules/npm/node_modules/slide/lib/chain.js:7:26)
13 verbose cwd /Users/mshick/code/project
14 error Darwin 15.0.0
15 error argv "/usr/local/Cellar/node/4.2.1/bin/node" "/Users/mshick/.node/bin/npm" "outdated"
16 error node v4.2.1
17 error npm  v3.3.6
18 error Cannot read property 'name' of undefined
19 error If you need help, you may report this error at:
19 error     <https://github.com/npm/npm/issues>
20 verbose exit [ 1, true ]

Your marketing on Lo-Dash and size is incorrect.

Underscore/lodash is large, and you have to manually create custom builds when if you're trying to optimize for size.

That's not entirely accurate. Underscore doesn't support custom builds and Lo-Dash provides module bundles for AMD & Node as well as npm packages.

Lo-Dash 3.0 will also officially support ES6 modules as well as paths such as require('lodash/object/clone') out of the box 😀

Add a `flip()` function

I've been reading issue #16 (closed now), and just wanted to bump the idea of having a flip() function.

The original proposition by @jfsiii:

flip (or reverseArguments, etc)

function flip(fn) {
  return function() {
    var args = [].slice.call(arguments).reverse();
    return fn.apply(this, args);
  };
}

It might seem silly to have a function which just reverses argument order, but it's a great help when you want to invoke a existing function which does what you want/need but has arguments in the opposite order.

Why it's great

In addition to the arguments posted already, I see one great use case – currying right-hand-side arguments.

In the JS world this is common: doGreatStuff(target, options). A function with optional arguments or an options object listed on the very right.

I often want to .bind() the optional arguments. Wouldn't it be great to do flip(doGreatStuff).bind(null, {candyFloss: true})?

or doesn't return boolean

As the jsdoc of or states, or should return a boolean.

/**
 * Functional version of ||
 * @function module:101/and
 * @param {*} a - any value
 * @param {*} b - any value
 * @return {boolean} a || b
 */

But it returns the value passed to the function, if it is thruthy.

var or = require('./or');
or(1, false);
// => 1
or("101", false);
// => "101"

I have a PR ready if you want to change this behaviour.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.