These are chat archives for ramda/ramda

2nd
Dec 2016
Morten Poulsen
@mspoulsen
Dec 02 2016 12:58
Hi guys...is there and easy / elegant way to do a deepMap over a nested object? :smiley:
Denis Stoyanov
@xgrommx
Dec 02 2016 13:14
@mspoulsen evolve?
Morten Poulsen
@mspoulsen
Dec 02 2016 13:17
@xgrommx With evolve we would need knowledge of the keys, right?
name of keys
Denis Stoyanov
@xgrommx
Dec 02 2016 13:18
@mspoulsen yes
Morten Poulsen
@mspoulsen
Dec 02 2016 13:19
I made a small recursive function and it works fine. Was just wondering if something like deepMap was built in to ramda. But thanks anyway :thumbsup:
I need it for a search and replace for nulls
Xia L
@laoqiren
Dec 02 2016 13:24
hello,everyone
so cute, I'm learning functional javascript recently
Jonah
@jonahx
Dec 02 2016 13:30
would love feedback on possible improvments to my ramda solution to part 1 of http://adventofcode.com/2016/day/1:
const [turns, steps] = ap([map(head), map(pipe(tail, add(0)))], [input]);
const arrAdd = pipe(zip, map(sum));
const answer = pipe(
  map(x => x == 'L' ? -1 : 1),                  // L becomes -1, R becomes 1
  scan(add, 0),                                 // each cell now sum of all previous cells
  tail,                                         // remove superfluous 0 scan puts at the start
  map(mathMod(__, 4)),                          // change each sum to an integer: 0 = N, 1 = E, 2 = S, 3 = W
  map(nth(__, [[0,1], [1,0], [0,-1], [-1,0]])), // change each direction integer to a step delta
  zip(steps),                                   // combine step delta with step size: [5, [0,1]]
  map(([c, arr]) => map(multiply(c), arr)),     // multiply it out: [0, 5]
  reduce(arrAdd, [0,0]),                        // sum them all element-wise
  map(Math.abs),                                // take absolute values of x and y coords
  sum                                           // sum those, you're done
)(turns);
Xia L
@laoqiren
Dec 02 2016 13:45
wow, your code is so cute
functional programming is so difficult
Kyle Chamberlain
@Koleok
Dec 02 2016 13:47
Embedding the gitter room in the docs site :muscle: :rocket: :joy: :tada:
great idea guys
Xia L
@laoqiren
Dec 02 2016 13:56
could you please follow me ?
Matt Ross
@amsross
Dec 02 2016 14:14
@Koleok embedding?
Kyle Chamberlain
@Koleok
Dec 02 2016 14:19
blob
Matt Ross
@amsross
Dec 02 2016 14:38
oh, on the main site
that’s pretty neat
LeonineKing1199
@LeonineKing1199
Dec 02 2016 16:09
@jonahx You might want to consider consider looking into transducers and seeing if you can reduce your code to a single pass. It's not always possible but when it is, it's pretty spiffy.
Jonah
@jonahx
Dec 02 2016 16:20
@LeonineKing1199, I’m not a huge fan of that method, in general — well, specifically if you are holding state in the object being transduced. To my mind, that’s just doing prodedural programming with local variables and an uglier syntax. Sorry if that’s not what you meant….
LeonineKing1199
@LeonineKing1199
Dec 02 2016 16:22
O_o
The innate hostile reaction towards a well-established paradigm is very telling. But transducers more or less compose map and reduce calls over an array into a single pass which is what it looks like your code is doing which is why I suggested it.
Jonah
@jonahx
Dec 02 2016 16:27
@LeonineKing1199 not hostile at all :) "Sorry if that’s not what you meant….” was specifically meant to clarify my open-mindedness to disucussion and openness to the possibility that I was missing something.
If you provided an example of the rewrite you were suggesting maybe that would help.
What I was saying is that you can often rewrite standard loops with a reduce statement and an object that holds the temporary state in some keys and the “result” state in another key — to me, that’s an escape hatch into normal procedural programming with a veneer of functional.
again, that may not have been what you were suggesting.
Denis Stoyanov
@xgrommx
Dec 02 2016 16:32
@jonahx your code has wrong answer. For "R4, R3, L3, L2, L1, R1, L1, R2, R3, L5, L5, R4, L4, R2, R4, L3, R3, L3, R3, R4, R2, L1, R2, L3, L2, L1, R3, R5, L1, L4, R2, L4, R3, R1, R2, L5, R2, L189, R5, L5, R52, R3, L1, R4, R5, R1, R4, L1, L3, R2, L2, L3, R4, R3, L2, L5, R4, R5, L2, R2, L1, L3, R3, L4, R4, R5, L1, L1, R3, L5, L2, R76, R2, R2, L1, L3, R189, L3, L4, L1, L3, R5, R4, L1, R1, L1, L1, R2, L4, R2, L5, L5, L5, R2, L4, L5, R4, R4, R5, L5, R3, L1, L3, L1, L1, L3, L4, R5, L3, R5, R3, R3, L5, L5, R3, R4, L3, R3, R1, R3, R2, R2, L1, R1, L3, L3, L3, L1, R2, L1, R4, R4, L1, L1, R3, R3, R4, R1, L5, L2, R2, R3, R2, L3, R4, L5, R1, R4, R5, R4, L4, R1, L3, R1, R3, L2, L3, R1, L2, R3, L3, L1, L3, R4, L4, L5, R3, R5, R4, R1, L2, R3, R5, L5, L4, L1, L1" result should be 288
Jonah
@jonahx
Dec 02 2016 16:33
@xgrommx it assumes is already an array. it works, as i’ve submitted my answer and it was correct.
sorry for the confusion
LeonineKing1199
@LeonineKing1199
Dec 02 2016 16:34

What I was saying is that you can often rewrite standard loops with a reduce statement and an object that holds the temporary state in some keys and the “result” state in another key — to me, that’s an escape hatch into normal procedural programming with a veneer of functional.
again, that may not have been what you were suggesting.

Actually, I'd always suggest that. Multi-paradigm programming is the bees knees, man.

Denis Stoyanov
@xgrommx
Dec 02 2016 16:35
input.split(' ,')
           .map(([direction, step]) => ({direction, step: parseInt(step})
           .reduce(({facing, x, y}, {direction, step}) => ..., {facing: 0, x: 0, y: 0})
Jonah
@jonahx
Dec 02 2016 16:37
I’d agree there are times when some temp variables and loop gives you cleaner solution. if it’s one of those times, i think you should do that as it’s generally shorter and clearer than hiding what you’re doing in a reducer object. ymmv, not really a point i care to go to the mat on :)
@xgrommx, yes that’s a perfect example of what i’m talking about. if you want to take that approach (and that was my initial way of approaching it too), i’d rather just make facing, x, and y local variables that you mutate.
it’s literally just a different syntax for that, and the “normal” procedural syntax of declariing and initializing variables at the top is actaully cleaner imo
Brad Compton (he/him)
@Bradcomp
Dec 02 2016 16:58
Ramda's transducers are nice in that you can write code that looks like normal maps and whatnot, but under the hood they are evaluated in a single pass. You don't need to worry about holding onto the state.
Denis Stoyanov
@xgrommx
Dec 02 2016 19:30
This message was deleted
This message was deleted
ram-bot
@ram-bot
Dec 02 2016 19:31
Unexpected token {
Denis Stoyanov
@xgrommx
Dec 02 2016 19:31
@jonahx
R.compose(
  ({x, y}) => Math.abs(x) + Math.abs(y),
  R.reduce(({facing, x, y}, [dir, ...step]) =>       
       R.converge((facing, coord) => Object.assign({}, {facing}, coord), [R.identity, R.cond([
         [R.equals(0), (_, s, x, y) => ({x, y: y + s})],
         [R.equals(2), (_, s, x, y) => ({x, y: y - s})],
         [R.equals(1), (_, s, x, y) => ({x: x + s, y})], 
         [R.equals(3), (_, s, x, y) => ({x: x - s, y})]
       ])])(
         facing === 0 && dir === 'L' ? 3 : (facing === 3 && dir === 'R' ? 0 : facing + (dir === 'R' ? 1 : -1)),
         parseInt(step.join('')),
         x, y
       )
     , {facing: 0, x: 0, y: 0}),
  R.split(', ')
)("R4, R3, L3, L2, L1, R1, L1, R2, R3, L5, L5, R4, L4, R2, R4, L3, R3, L3, R3, R4, R2, L1, R2, L3, L2, L1, R3, R5, L1, L4, R2, L4, R3, R1, R2, L5, R2, L189, R5, L5, R52, R3, L1, R4, R5, R1, R4, L1, L3, R2, L2, L3, R4, R3, L2, L5, R4, R5, L2, R2, L1, L3, R3, L4, R4, R5, L1, L1, R3, L5, L2, R76, R2, R2, L1, L3, R189, L3, L4, L1, L3, R5, R4, L1, R1, L1, L1, R2, L4, R2, L5, L5, L5, R2, L4, L5, R4, R4, R5, L5, R3, L1, L3, L1, L1, L3, L4, R5, L3, R5, R3, R3, L5, L5, R3, R4, L3, R3, R1, R3, R2, R2, L1, R1, L3, L3, L3, L1, R2, L1, R4, R4, L1, L1, R3, R3, R4, R1, L5, L2, R2, R3, R2, L3, R4, L5, R1, R4, R5, R4, L4, R1, L3, R1, R3, L2, L3, R1, L2, R3, L3, L1, L3, R4, L4, L5, R3, R5, R4, R1, L2, R3, R5, L5, L4, L1, L1")
Jonah
@jonahx
Dec 02 2016 21:12
@xgrommx, here was my procedural version of that approach, not totally polished, but still to my eye more readable:
const turns='L5,R1,R3,L4,R3,R1,L3,L2,R3,L5,L1,L2,R5,L1,R5,R1,L4,R1,R3,L4,L1,R2,R5,R3,R1,R1,L1,R1,L1,L2,L1,R2,L5,L188,L4,R1,R4,L3,R47,R1,L1,R77,R5,L2,R1,L2,R4,L5,L1,R3,R187,L4,L3,L3,R2,L3,L5,L4,L4,R1,R5,L4,L3,L3,L3,L2,L5,R1,L2,R5,L3,L4,R4,L5,R3,R4,L2,L1,L4,R1,L3,R1,R3,L2,R1,R4,R5,L3,R5,R3,L3,R4,L2,L5,L1,L1,R3,R1,L4,R3,R3,L2,R5,R4,R1,R3,L4,R3,R3,L2,L4,L5,R1,L4,L5,R4,L2,L1,L3,L3,L5,R3,L4,L3,R5,R4,R2,L4,R2,R3,L3,R4,L1,L3,R2,R1,R5,L4,L5,L5,R4,L5,L2,L4,R4,R4,R1,L3,L2,L4,R3'.split(',')

var d  = 0;
var xy = [0, 0];

const arrAdd = pipe(zip, map(apply(add)));
const delta = [[0,1], [1,0], [0,-1], [-1,0]]; // N, E, S, W
const newDir = (d, isL) => mathMod(d + (isL ? -1 : 1), 4);
const move  = (d, dist) => arrAdd(xy, map(multiply(dist), delta[d]));

turns.forEach(t => {
  d = newDir(d, t[0] == 'L');
  xy = move(d, parseInt(t.slice(1)));
})

console.log( sum(map(Math.abs,xy)) );