These are chat archives for ramda/ramda

22nd
Jan 2018
Are
@are1000
Jan 22 2018 08:25
@paldepind I don't think that it would be hard to write a primitive version of a tool like this
@paldepind just change args and expected.
Are
@are1000
Jan 22 2018 08:30
alas it only works for primitive values.
Are
@are1000
Jan 22 2018 09:02
And this one works for arrays and objects: https://goo.gl/3BTfVv
Are
@are1000
Jan 22 2018 09:55
Btw, can someone tell me why this input in Ramda REPL crashes whole tab?
let args = [x => x + 2, [ 1, 2, 3 ] ]
let expected = [3, 4, 5]

let results = []

for (let fnName of Object.keys(R)) {
  try {
    let tres = R[fnName](...args)
    if (R.equals(tres, expected)) {
      results.push(fnName)
    }
  } catch (e) {

  }
}

results
Frank Stokes
@francisrstokes
Jan 22 2018 10:01
@lax4mike the example in the docs has a good illustration of possible use case. reduce(subtract, 0, [1,2,3,4]) would give -10, and reversing the array would still give -10. Because subtract(a, b) is implemented as a - b, the acc is always in the a position, meaning in the first step you'd get (0 - 4), (-4 - 3), ... - already wrong. reduceRight solves the problem by flipping the order that those arguments come in, giving you (4 - 0), (4 - 3), ...
Francisco
@franciscotln
Jan 22 2018 10:15
@are1000 because your try/catch is not working. This works: https://goo.gl/NRAZH8
const args = [ add(2), range(1, 4) ];

const expected = [ 3, 4, 5 ];

const results = [];

compose(
  forEach(fnName => {
    tryCatch(args => {
      const fn = prop(fnName, R);
      const tres = apply(fn, args);
      if (equals(tres, expected)) {
        results.push(fnName);
      }
    }, F)(args);
  }),
  keys
)(R);

results;
Are
@are1000
Jan 22 2018 10:16
Why is it not working?
Francisco
@franciscotln
Jan 22 2018 10:16
I can't answer to that question :D I just know where the problem is. Perhaps something with the REPL itself
Are
@are1000
Jan 22 2018 10:19
@franciscotln nope, it crashes Node.js too with heap out of memory
Should it happen tho?
Francisco
@franciscotln
Jan 22 2018 10:35
strange, strange :-) @are1000 , look, this works:
const args = pair(add(2), range(1, 4));

const expected = [3, 4, 5];

const results = []

for (const fnName in R) {
  try {
    const condition = o(
      equals(expected),
      apply(R[fnName])
    )(args);
    if (condition) {
      results.push(fnName)
    }
  } catch (e) {
    // do nothing.
  }
}

results;
Are
@are1000
Jan 22 2018 10:36
this is definitely weird. I have opened an issue in Ramda repo, just to be sure. #2445
Feel free to add more info if you feel like somethings missing!
Francisco
@franciscotln
Jan 22 2018 10:38
this also works:
  try {
    const fnCall = apply(R[fnName], args);
    if (equals(expected, fnCall)) {
      results.push(fnName)
    }
  } catch (e) {
    // do nothing.
  }
Are
@are1000
Jan 22 2018 10:40
I think something bad is happening, when uncurryN is called
Or a function after uncurryN
yep, its unfold that crashes
Francisco
@franciscotln
Jan 22 2018 10:42
ok
now I know exactly when it crashes :D
the problem is in the first line
Are
@are1000
Jan 22 2018 10:43
var pair = fn(seed);?
Francisco
@franciscotln
Jan 22 2018 10:43
keep the code exactly the way you posted first and in the first line, instead of x => x + 2 use add(2)
the problem is with the fat arrow as first array item
for some reason it crashes with the fat arrow
but with add(2) it works fine
Are
@are1000
Jan 22 2018 10:43
But this is ridiculous :O
Francisco
@franciscotln
Jan 22 2018 10:44
I know, right? :D
but I just tested it
Are
@are1000
Jan 22 2018 10:44
Wow, I think we just discovered some nasty bug?
Francisco
@franciscotln
Jan 22 2018 10:44
the code you posted works when you change the fat arrow to the add(2) function
Are
@are1000
Jan 22 2018 10:45
anonymous function also doesn't work.
Francisco
@franciscotln
Jan 22 2018 10:45
yea
Are
@are1000
Jan 22 2018 10:45
function (x) { return x + 2 }
Francisco
@franciscotln
Jan 22 2018 10:45
just tested with this
simply doesnt work
but why does it work with add(2) :D
Are
@are1000
Jan 22 2018 10:46
I think we need to dive into R.add and discover its magic
it does three things:
  1. coerces to Number
Francisco
@franciscotln
Jan 22 2018 10:46
var add = _curry2(function add(a, b) {
  return Number(a) + Number(b);
});
export default add;
Are
@are1000
Jan 22 2018 10:46
Yep, I think its _curry2
Francisco
@franciscotln
Jan 22 2018 10:48
this works: const args = [ a => Number(a) + 2, [1, 2, 3] ];
so it's the coercion
that makes add() work
Are
@are1000
Jan 22 2018 10:49
but what else could a be?
Francisco
@franciscotln
Jan 22 2018 10:49
array [1,2,3]
Are
@are1000
Jan 22 2018 10:50
wow, when you put a console.log inside the function
it turns out that 2 gets printed indefinitely
Francisco
@franciscotln
Jan 22 2018 10:50
and in one call it is a function
take a look: https://goo.gl/upFG8u
Are
@are1000
Jan 22 2018 10:51
ok, that is understandable
but somewhere in unfold it gets stuck in an infinite loop
printing 2
when for gets into unfold, it prints this:
[ 1, 2, 3 ]
,
2
2
2
2
2
...
and 2 ad infinitum
Francisco
@franciscotln
Jan 22 2018 10:53
yeah
Well, now you know: use x => Number(x) + 2 and it will work :D
Are
@are1000
Jan 22 2018 10:54
but I'm pretty sure it shouldn't just crash like this?
oooh, ok, I get it
I know what's happening.
var unfold = _curry2(function unfold(fn, seed) {
  var pair = fn(seed);
  var result = [];
  while (pair && pair.length) {
    result[result.length] = pair[0];
    pair = fn(pair[1]);
  }
  return result;
});
export default unfold;
first, you pass x => x + 2 and [1, 2, 3]
then pair = "1,2,32"
Francisco
@franciscotln
Jan 22 2018 10:56
yeah that's where it gets stuck :-)
Are
@are1000
Jan 22 2018 10:56
and then you enter a while loop that never terminates, because you are never modifying the pair in such a way that it reduces to length 0
and in the loop you keep adding 1 into the result array and setting pair to ,2 and later 22.
Francisco
@franciscotln
Jan 22 2018 11:05
Perhaps there should be some kind of type checking inside R.unfold, it's really easy to break it
Are
@are1000
Jan 22 2018 11:10
Well, this could pose a problem, because Ramda community didn't want to typecheck at all.
Although this should definitely not happen.
And what I mean is infinite loops without terminating them.
Simon Friis Vindum
@paldepind
Jan 22 2018 11:37
@are1000 Yes, I agree. I'm working on a proof of concept :smile:
Are
@are1000
Jan 22 2018 12:49
Folks, how to check if array contains only the same elements?
fn([ 1, 1, 1 ]) // true
fn([ "b", "b", "b" ]) // true
fn([ 3, "3", 3 ]) // false
fn([ 1, 2, 3 ]) // false
Ok, got it, can someone verify?
let f = R.compose(
  R.equals(1),
  R.prop('length'),
  R.uniq
)

f([ 1, 1, 1 ]) // true
f([ 1, "1", 1 ]) // false
f([ 1, 2, 3 ]) // false
Francisco
@franciscotln
Jan 22 2018 13:54
all(equals(1)) ?
Are
@are1000
Jan 22 2018 14:09
@franciscotln I don't know what will be the element.
I just want to know if all elements are the same.
Tomas Lieberkind
@lieberkind
Jan 22 2018 14:39
@are1000 I suppose you could substitute R.prop('length') with R.length if you want to avoid using a string to access the length property of the list?
Are
@are1000
Jan 22 2018 14:41
Definitely! Less magical primitives, the better! Thanks @lieberkind!
Tomas Lieberkind
@lieberkind
Jan 22 2018 14:43
np :)
Francisco
@franciscotln
Jan 22 2018 16:39
I don't know if you want to get false if the array is empty (in my reasoning an empty array should also return true because all "elements" equal "undefined") @are1000
in this case this solution fails because you require the length to be 1
This works for the case of an empty array as well (meaning that it returns true):
// [] => true
// [1] => true
// [1, 1] => true
// [1, "1"] => false
// [1, 2] => false

const allEqual = chain(compose(all, equals), head);
Matthew Willhite
@miwillhite
Jan 22 2018 16:46
@are1000 You could use sanctuary-def to type your function (depending on how you plan to use this) as the default expects arrays to be homogeneous
joao@kapmug
@jay-jlm
Jan 22 2018 20:23
Hi, I'm new to Ramda.. can you guys let me know how can I improve on this code? Thank you!
const containsDeep  = (val, searchValue) => {
     if (R.type(val) === 'Object') {
       const  findInObj = Object.entries(val).map(([k, v]) =>  containsDeep(v, searchValue))
       return R.any((v) => v === true, findInObj)
     } else if(R.type(val) === 'Array') {
       const  findInArray = val.map(el =>  containsDeep(el, searchValue))
       return R.any((v) => v === true, findInArray)
     } else {
       if(val === searchValue) return true
     }
     return false
}
joao@kapmug
@jay-jlm
Jan 22 2018 20:32
this part I suspect could be more semantic >> R.any((v) => v === true, func). Basically I need to know if any of the array elements is true (or truthy)
Vasili Sviridov
@vsviridov
Jan 22 2018 20:36
@jay-jlm can use R.is(Object) as a predicate instead of (val) => R.type(val) === 'Object')
can also use R.cond instead of series of if-else statements...
also, ramda's map takes both objects and arrays, so you might not need the distinction between them.
Vasili Sviridov
@vsviridov
Jan 22 2018 20:55
for some reason the playgroud gives me "too much recursion" error if I inline the checkers or partially apply them
joao@kapmug
@jay-jlm
Jan 22 2018 21:21
thanks guys, I will take a look!
appreciated!
Francisco
@franciscotln
Jan 22 2018 23:23
@jay-jlm I'm not sure that your solution works for object. I tried it on REPL and it did not found nested values. In any case you may want to check this out: https://goo.gl/g1DpUD
first point: you might want to have containsDeep curried to partially apply it in the recursion.
second point: invert the parameters order so that you can have it curried properly
third point: as it was mentioned above: R.map works for object and arrays
R.cond is not necessary because you actually have only two cases, so R.ifElse is enough
forth point: it's better to use R.is instead of R.typebecause R.is(Object) covers both Object and Array at once unless you know that some function may appear in there (because R.is(Object, function(){}) returns true), then you should opt for R.type.
Francisco
@franciscotln
Jan 22 2018 23:36
const containsDeep = R.curry((searchValue, val) =>
  R.ifElse(R.is(Object),
    R.pipe(
      R.map(containsDeep(searchValue)),
      R.values,
      R.any(R.equals(true)),
    ),
    R.equals(searchValue)
  )(val)
);

containsDeep('deep', [[['deep']]]); // true
containsDeep('deep', 'deep'); // true
containsDeep('deep', { a: { b: 'deep' } }); // true