selfrefactor / rambda Goto Github PK
View Code? Open in Web Editor NEWFaster and smaller alternative to Ramda
Home Page: https://selfrefactor.github.io/rambda
License: MIT License
Faster and smaller alternative to Ramda
Home Page: https://selfrefactor.github.io/rambda
License: MIT License
hello @selfrefactor ,
Are you willing to accept an implementation for R.reduce()
? Or is it out of scope?
Thank you and keep the good work.
Rambda's
reverse
modifies the array, instead of returning reversed copy of it.
Just wanted to ask why? When you create a new reversed array it's probably just a shallow copy. There's no need to "fight" for RAM too much as JS already has memory sharing built-in. It's just not protected sharing and we protect it by convention with Ramda approach.
let xs = [{...}, {...}, {...}]
//
let ys = [xs[2], xs[1], xs[0]]
ys
does not double the memory usage. It's only additional pointers (4 bytes each)!
I.m.o the convention of "every function here is immutable" has to be kept at any cost.
Hello, me again :)
I would like to see ramda's forEach
and times
methods added to rambda
:
http://ramdajs.com/docs/#forEach
http://ramdajs.com/docs/#times
I use these methods all the time and am missing them dearly from rambda
:'(
Using Typescript 2.5.2, errors are emitted because of the syntax used in the definition file for this project.
On rambda 0.9.3, in index.d.ts, on lines 387 and 388, the syntax is wrong.
without(listToOmit: any[], originalList: any[]): list: any[];
without(listToOmit: any[]): (originalList: any[]) => list: any[];
I'm not an expert on Typescript, but list: any[]
at the end looks like a mistake.
The error specifically is Expecting new line or semicolon
. Because this line is broken, you get other errors down the road, like TS2304: Cannot find name 'without'.
which is a method I'm assuming was added recently.
Hi, I am looking for a chain
or flatMap
function, but can't find it. Is there such a function and if so, what is it's name? If not, is there a special reason and might I submit a pull request to add it?
My bad, I forgot to submit this as part of my original PR. I'll create another PR to resolve this issue :)
Hi,
I understand this has to do with curry, but I constantly have trouble with R.is because of this, so...
The troube comes when I do something like this
if (R.is(Array, someVar)) { ... }
Now, if someVar is undefined then R.is will return function, so the check will pass.
This may happen in a bigger scope, when my function accepts an object A, and one of its fields B should be an array:
function myFunc(A) {
...
if (R.is(Array, A.B)) { ... }
...
}
So, if B was not defined, the IF block will proceed as if B were an array.
I can add an additional check
if (A.B && R.is(Array, A.B)) { ... }
But that just doesn't feel and look right. Right?
We were looking at using Rambda instead of Ramda because of the speed, size and complexity benefits but we weren't huge fans of the current Curry implementation.
We liked that you say you're currying at call rather than implementation because it removes the ambiguity over whether the function you were calling is curried or not, but disliked that you have to change the interface of the original function to support it.
Is there a specific reason you went with this implementation rather than something like:
https://gist.github.com/danrspencer/a81fd5702d7d565c470b1566453f71a7
?
When using the latest version of rambda, it breaks in IE as the code is untranspiled es6.
Hi,
R.forEach as I see in source is just a proxy to R.map, but returns original data.
So it seems natural to pass Objects to R.forEach (just like R.map). But unfrotunately second argument (prop) is lost in iterate function.
R.map((val,prop) => ...prop is OK here..., {...})
R.forEach((val,prop) => ...prop is undefined here..., {...})
Otherwise R.forEach loops over object's properties just fine.
Is it possible to make prop available inside forEach iterate func?
Thanks!
Does rambda or rambdax include a converge function that is equivalent to the converge function in ramda?.
In my opinion Ramda's curry
handles two things not particularly well.
this
properlylet assert = require("assert")
function curryN(N, fn) {
let self = undefined
let collectFn = Object.defineProperties(function (...args) {
if (this) {
self = this
}
if (args.length >= N) {
return fn.apply(self, args)
}
else {
return Object.defineProperties(function (...args2) {
if (this) {
self = this
}
return collectFn.apply(self, args.concat(args2))
}, {
name: {value: fn.name + "_" + args.length},
length: {value: N - args.length},
})
}
}, {
name: {value: fn.name},
length: {value: N}
})
return collectFn
}
let curry = function (fn) {
return curryN(fn.length, fn)
}
let sum3 = curry(function mySum(x, y, z) {
return x + y + z
})
let getSelf = curry(function (x) {
return this
})
let getSelf2 = curry(function (x, y) {
return this
})
// TEST LOGIC
assert.equal(typeof sum3(1), "function")
assert.equal(typeof sum3(1, 2), "function")
assert.equal(typeof sum3(1)(2), "function")
assert.equal(sum3(1)(2)(3), 6)
// TEST NAMES
assert.equal(sum3.name, "mySum") // !!!
assert.equal(sum3(1).name, "mySum_1") // !!!
assert.equal(sum3(1)(2).name, "mySum_2") // !!!
// TEST LENGTHS
assert.equal(sum3.length, 3)
assert.equal(sum3(1).length, 2)
assert.equal(sum3(1)(2).length, 1)
// TEST this BINDING
let self = {foo: "foo"}
assert.deepEqual(getSelf.bind(self)(null), self)
assert.deepEqual(getSelf2.bind(self)(null, null), self)
assert.deepEqual(getSelf2.bind(self)(null)(null), self) // !!!
assert.deepEqual(getSelf2(null).bind(self)(null), self)
Now the original R.curry
fails the tests marked with !!!
.
I raised this issue earlier I think, but they told me they don't want to support this
at all or something like that. As for names it can be argued against (fake). I personally believe having names like above is very helpful at debugging.
I'm interested what do you think.
Currently this module can't be used in production with webpack as it is es6 and isn't supported by the webpack uglify module.
Can you compile the package to es5 first with either babel or something else, before building with webpack.
R.equals( new Date('1/1/2017'), new Date('1/1/2018') ) // => true
Hi, fan of ramda and looking for smaller and faster implementation, arrived to your rambda. I was curious about the implementation and I'd like to ask: for example prepend
method (as far as I can see in the code) modify the argument (the array). The statement const clone = arr
do not clone array, co modifying clone
will modify the arr
.
Or am I wrong...?
BTW: I like the way you curry most of the functions. Not sure about if it can lead to some issues (arguments are passed to the function but undefined), but as a trade-off why not.
I've noticed that you now have to set the NODE_ENV variable in your process when using the package, otherwise you get the following error.
Module build failed: ReferenceError: Unknown plugin "external-helpers" specified in "/home/travis/build/jpgorman/react-append-to-body/node_modules/rambda/.babelrc.env.development"
Why is there no flatMap operation? It's not only very useful, it's also the bind operation for the list monad, so it's kind of heresy to omit it from a "functional" library ;)
There's a "flatten" in rambda, but because it flattens recursively, one can't simply define flatMap as compose(flatten, map).
So please consider adding a non-recursive shallowFlatten and also 'flatMap' (ideally an optimized one, but one based on map and shallowFlatten would also do).
Also a 'scan' operation (similar to reduce but building a list of the result of each iteration instead of giving just the end-result) would be useful (but far less important as flatMap).
Another useful operation would be somethink like "any" which would only test for 'undefined' and return the first non-undefined result of the iteration. This is useful to return the first successful application of a value to some operation (similar to 'find' but returning an arbitrary value instead of the found element).
R.omit('foo,bar,baz', {a: 1, foo: 2}) => {a: 1}
R.not(true); //=> false
R.not(false); //=> true
R.not(0); //=> true
R.not(1); //=> false
/es
package entry point is conventional in modern libraries.
The suggestion is to provide rambda/es
imports in ES5 and ES module format , similarly to how it was done with ramda/es
. Notice that Ramda modules are transpiled to ES5 to skip transpilation on bundling, and there is index reimporting file.
The package has rambda/lib
which is CJS. It doesn't have index (there will be problems with tree-shaking any way) and requires to use module interop when imported as ES modules, this results in increased footprint.
Self explanatory with title
Seems to be pipe
method is missing from index.d.ts
so Typescript cannot find it, but this method is presented in modules
folder and in the documentation.
Trying to build a create-react-app with Rambda dependency and have this error:
Failed to minify the code from this file:
./node_modules/rambda/dist/rambda.esm.js:3
Read more here: http://bit.ly/2tRViJ9
Version is 1.1.3 but also tried 1.1.1 with same result.
First off, i like your work! Its really cool to learn fp style without reading through dozens lines of code :).
I know you copied the curry function from a gist comment 😄 , i took some time to learn how it works and notices a problem - especially when its used together with reduce
Problem in one sentence: If the curried function is called with too many arguments, it will return a new curried function instead of calling the final function. Also the new curried function will now return again a new curried function for every further attempt.
https://github.com/selfrefactor/rambda/blob/master/modules/curry.js#L4
...
o.length === f.length
...
A basic example (ES6):
const add = curry((n, n2) => n + n2
add(1, 2, 3)
// result: function
// desired: 3
Reduce example:
const add = curry((n, n2) => n + n2)
reduce(add, 0, [1, 2, 3])
// result: function
Reduce calls the add function not only with acc and value, but also with index and array
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
o.length === f.length
to o.length >= f.length
R.equals([ true, false], [false, true] ) // => true
There is a wrong example for append
R.append('foo', ['bar', 'baz']) // => ['foo', 'bar', 'baz']
Should be:
R.append('foo', ['bar', 'baz']) // => ['bar', 'baz', 'foo']
'foo'
is added to the end.
0.9.7
was published recently which now bundles JS which is ES6 rather than ES5.
This is a breaking change and therefore should be a major version bump due to consuming projects now requiring an ES6 compliant environment.
Would it be possible to revert these changes and release a new patch, and then release the change to ES6 as a major version bump (e.g 1.0.0
)?
Currently both methods are part of Rambdax
I feel that they could be more useful as part of Rambda
API, but I will wait Rambda users to decide that.
Please comment if you have opinion on the topic.
composeAsync(fn1: Function|Async, .. , fnN: Function|Async)(startValue: any): Promise
compose
that accepts async
functions as argumentsmapAsync(fn: Async|Promise, arr: Array): Promise
Sequential asynchronous mapping with fn
over members of arr
const fn = a => new Promise(resolve => {
setTimeout(() => {
resolve(a + 100)
}, 100)
})
const result = await R.composeAsync(
R.mapAsync(async a => await fn(a)),
R.mapAsync(fn),
R.map(a => a * 10)
)([1, 2, 3])
expect(result).toEqual([210, 220, 230])
I believe that we should use a linter, as then contributing to the repo would be easier and everyone would be using same coding conventions.
change current typing which is
defaultTo<T, U>(a: T, b: U): T | U
defaultTo<T>(a: T): <U>(b: U) => T | U
I've noticed that a lot of functions have a check whether the arguments are defined inside of them.
To cut down on size, wouldn't it be better to just wrap them in curry functions ?
R.path('a', undefined) => [Function]
There is currently an issue with inconsistent and faulty typings.
One way to solve it is to let Typescript build the definitions.
How many parameters can have the right most function?
work using more than one parameter?
const result = R.compose(
R.map(x => x * 2),
(a, y) => R.filter(x => x > y, a)
)([1, 2, 3, 4], 2)
// => []
Have I write a wrong example?
regards
I check this in ramda
, it has zipObj
.
R.includes("foo")(["foo","bar]) => true
Hey @selfrefactor me again—it's been a while!
Would you mind making all exported functions modules—so they can be imported separately?
The functions that are currently only declared in rambda.js
are:
I would like to be able to import these functions from the lib
like so:
import identity from 'rambda/lib/identity'
R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c']
I'm curious, since partial application is a powerful feature for composing new functions, why haven't you added R.__
or R.flip
?
While the lib code may only be 10kb, the install on disk is almost 3MB
$ disk-usage | grep rambda
2.9M rambda
It comes with the whole repo:
ls -o
total 640
-rw-r--r-- 1 tkye 1891 Oct 26 1985 CONTRIBUTING.md
-rw-r--r-- 1 tkye 1069 Oct 26 1985 LICENSE
-rw-r--r-- 1 tkye 54739 Oct 26 1985 README.md
drwxr-xr-x 39 tkye 1326 Jun 26 14:55 __tests__
drwxr-xr-x 33 tkye 1122 Jun 26 14:55 benchmarks
drwxr-xr-x 8 tkye 272 Jun 26 14:55 dist
drwxr-xr-x 5 tkye 170 Jun 26 14:55 docs
drwxr-xr-x 13 tkye 442 Jun 26 14:55 files
-rw-r--r-- 1 tkye 19619 Oct 26 1985 index.d.ts
drwxr-xr-x 99 tkye 3366 Jun 26 14:55 lib
drwxr-xr-x 99 tkye 3366 Jun 26 14:55 modules
-rw-r--r-- 1 tkye 3067 Jun 26 14:55 package.json
-rw-r--r-- 1 tkye 5129 Oct 26 1985 rambda.js
-rw-r--r-- 1 tkye 11807 Oct 26 1985 webVersion.js
-rw-r--r-- 1 tkye 214780 Oct 26 1985 yarn.lock
You should consider using the files
property on package.json
to reduce this size. Things like __tests__
don't need to ship with the installation
As far as I can tell defaultsTo(defaultArgument, inputArgument)
is the only method that provides a way for defaulting to a value (providing some 'or' logic). However, the built-in test for inputArgument
being the same type
as defaultArgument
limits the use of this function. It is my opinion that defaultArgument
should only be returned if inputArgument
is undefined
.
I would like to compose a function works the same as Lodash's get
method or Ramda's pathOr
method whereby a value is read from a path through a nested object tree and defaults to a value if this path returns undefined
.
import { get } from 'lodash'
import { pathOr } from 'ramda'
import { curry, defaultsTo, path } from 'rambda'
// Tests written with jest
test('lodash get', () => {
expect(get({ a: { b: 2 } }, 'a.b')).toBe(2)
expect(get({ c: { b: 2 } }, 'a.b')).toBeUndefined()
expect(get({ c: { b: 2 } }, 'a.b', 'N/A')).toBe('N/A')
})
test('ramda pathOr', () => {
// From ramda's docs http://ramdajs.com/docs/#pathOr
expect(pathOr('N/A', ['a', 'b'], { a: { b: 2 } })).toBe(2)
expect(pathOr('N/A', ['a', 'b'], { c: { b: 2 } })).toBe('N/A')
})
// There's probably a more elegant way of doing this?
const rambdaPathOr = curry((defaultValue, inputPath, inputValue) =>
defaultTo(defaultValue, path(inputPath, inputValue)))
test('rambda pathOr', () => {
// This first test fails because the value of a.b is 2 (type 'Number')
// and is a different type to the default value 'N/A' (type 'String')
expect(rambdaPathOr('N/A', ['a', 'b'], { a: { b: 2 } })).toBe(2)
expect(rambdaPathOr('N/A', ['a', 'b'], { c: { b: 2 } })).toBe('N/A')
})
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.