These are chat archives for ramda/ramda

4th
Dec 2018
Harry Solovay
@harrysolovay
Dec 04 2018 03:38
Couldn't get it working :( I'm thinking that using a technique to eliminate passing the config arg twice will hit performance. I'm gonna take the easy way out and pass it twice. Very interesting thought processes though. I really appreciate you taking the time to think this through with me!
Alexander Lichter
@manniL
Dec 04 2018 10:45
Is there a smooth way to split an array and use a function as "split condition"?
Nvm, just found ramda/ramda#2688
Rakesh Pai
@rakeshpai
Dec 04 2018 14:15
Hi. Sorry for the n00b question, but is it not possible to use a reduce in a transducer passed into into?
All examples I've seen of transducers use either map or filter, but from my understanding of transducers, reduce should work too, no?
Scott Sauyet
@CrossEye
Dec 04 2018 14:41
@rakesh: Have you tried it? What would you want to use it for?
Rakesh Pai
@rakeshpai
Dec 04 2018 14:42
Tried it, but I get the following error:
/home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_reduce.js:60
  throw new TypeError('reduce: list must be array or iterable');
  ^

TypeError: reduce: list must be array or iterable
    at _reduce (/home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_reduce.js:60:9)
    at /home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_curry3.js:32:18
    at f1 (/home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_curry1.js:18:17)
    at /home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_pipe.js:3:27
    at /home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_arity.js:10:19
    at into (/home/rakesh/Projects/advent-of-code/node_modules/ramda/src/into.js:53:93)
    at /home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_curry3.js:32:18
    at f1 (/home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_curry1.js:18:17)
    at /home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_pipe.js:3:14
    at /home/rakesh/Projects/advent-of-code/node_modules/ramda/src/internal/_pipe.js:3:27
This is the relevant bit of my code:
  into([], compose(
    map(prop('sleepingMinutes')),
    reduce(flip(concat), []), // flatten, expressed as a reduce
  )),
I understand the bit about expressing map and filter as reducers, based on first principles, and how ramda does that implicitly. However, I'm just a little surprised that I can't add a reduce itself inside a transducer.
Rakesh Pai
@rakeshpai
Dec 04 2018 15:07
To clarify, what's passed in here is an array of objects, where the objects all have a .sleepingMinutes property, which is an array of numbers. What I want is to collect all the .sleepingMinutes of every object in the outer array, and make a flat list of out it.
Rakesh Pai
@rakeshpai
Dec 04 2018 15:18
Just pushed my code to github. I was wondering if it's possible to change this function to use transducers.
Alexander Lichter
@manniL
Dec 04 2018 15:49
Hey! Another one doing Advent of Code with Ramda :speak_no_evil:
Scott Sauyet
@CrossEye
Dec 04 2018 15:55
Hey, I saw that problem last night too. I think I'll need to try it.
Rakesh Pai
@rakeshpai
Dec 04 2018 15:56
@manniL :) Saw your messages above. Awesome!
It'd be great if anyone feels like constructively critiquing my code. I'd love to learn if there's better ways of doing what I'm doing.
Alexander Lichter
@manniL
Dec 04 2018 15:57
@rakeshpai Thanks for sharing your approaches :+1:
Yeah, same here :P
I feel like yours is way cleaner then mine :see_no_evil:
Scott Sauyet
@CrossEye
Dec 04 2018 15:58
But I've never thought about reduce in a transducer. If it's not working like that, I think it simply won't work. But I never remember great details about our transducers.
Alexander Lichter
@manniL
Dec 04 2018 15:58
And I already learned some nice ideas :relaxed:
Rakesh Pai
@rakeshpai
Dec 04 2018 16:04
@CrossEye Ok. I guess I just assumed that reduces would work in a transducer context. The docs don't say it or anything, so it's entirely my misunderstanding. Thrown off by the fact that transducers are based on reducers, so I just thought it'd fit right in. But I guess transducers only 'unroll' map and filter calls (and others that behave like it), but not reduce?
It still feels to me like reduce should work, intuitively. :)
Scott Sauyet
@CrossEye
Dec 04 2018 16:17

Since reduce is another transformation that seems like it should fit, it would make sense:

const weirdCalc = compose(map(factors), reduce(add, 0))
into([], weirdCalc, [14, 25]) // Should be [1 + 2 + 7 + 14, 1, 5, 25] => [28, 31]

Instead it throws an error. Would you like to raise an issue for this? Maybe one of our more transducer-knowledgeable people can give some insight.

Brad Compton (he/him)
@Bradcomp
Dec 04 2018 16:19
I can see scan being used as a transducer, but reduce returns a single value.
Rakesh Pai
@rakeshpai
Dec 04 2018 16:24
@CrossEye I wonder if the current behaviour is intentional. The docs don't say that reduce will tranduce, and the code for reduce in ramda doesn't seem to do anything special for transducers either.
Scott Sauyet
@CrossEye
Dec 04 2018 16:29

@Bradcomp : Yes, and my example above makes no sense. I keep thinking about one step of a transformation returning a list, and the next reducing that to a value. But that's not the right level. It would be a map call or something on that list of lists. So the above should actually be

const weirdCalc = compose(map(factors), map(reduce(add, 0)))
into([], weirdCalc, [14, 25]) // Should return [1 + 2 + 7 + 14, 1, 5, 25] => [24, 31]

But here the reducer is again map. (I even did the addition wrong in the original. D'oh!)

Mayer Lench
@mayerlench
Dec 04 2018 19:33

Ramda on many functions for instance assoc, says it creates a shallow clone.
My understanding is that a shallow clone is a reference. If you have a number Z and you create shallow cloned variables to X and Y, X and Y will reference your number Z

From what i see when Ramda talks about shallow clone it is not referenced and the functions return new copies
Maybe im misunderstanding, any explanations will really help, thanks!

Rakesh Pai
@rakeshpai
Dec 04 2018 19:39
const foo = {
  x: { a: 'b' },
  y: 'bar'
}

const clone = shallowClone(x);

foo === clone; // false. Top level cloned. References don't match
foo.x === clone.x; // true, This is deep, so references match
foo.y === clone.y; // true, values match
Brad Compton (he/him)
@Bradcomp
Dec 04 2018 19:40
Your example is correct.
Rakesh Pai
@rakeshpai
Dec 04 2018 19:48
@mayerlench To explain further, a shallow clone doesn't copy the reference - quite the opposite. It creates a new reference, and copies the top level properties over. However, it doesn't recurse through the object structure, so only the top level is copied over, while deeper levels are by reference. The cloning is shallow.
Mayer Lench
@mayerlench
Dec 04 2018 20:01
Great explanation, Thanks!
Zubeyr Dereli
@dereli
Dec 04 2018 20:03
Hey all. I am reading the documentation and noticed that for multiple functions, it mentions this: "Acts as a transducer if a transformer is given in list position." Is there any example that demonstrates this?
Scott Sauyet
@CrossEye
Dec 04 2018 20:05

We could imagine multiple levels of clone. clone-0 would create a new object with the same property names as your original, each referring to the same instances in your original. This is what is generally referred to as a shallow clone, as your example shows.

Then we could also imagine a clone-1 for which

const foo = {
  x: { a: {z: 'b'} },
  y: 'bar'
}

const clone = shallowClone(x);

foo === clone;         // false. Top level cloned. References don't match
foo.x === clone.x;     // false, This is level 1, so references don't match
foo.x.z === clone.x.z  // true, this is level 2, so references match
foo.y === clone.y;     // true, values match

... and so on. And of course we could then imagine clone-∞, at which all levels of properties share references. This is what's usually referred to as a deep clone.

@dereli: the into documentation has at least one example.
Rakesh Pai
@rakeshpai
Dec 04 2018 20:08
@CrossEye beat me to the answer! @dereli into looks like the easiest way to use transducers, but I could be wrong.
Scott Sauyet
@CrossEye
Dec 04 2018 20:08
That shows map and take. The transduce documentation shows the same with the addition of filter.
into is a gloss on transduce. It is easier to use, but transduce is more powerful. Use into when you can.
Zubeyr Dereli
@dereli
Dec 04 2018 20:20
Thanks @CrossEye and @rakeshpai, I think I understood what transducers are; If I try to simplify, they're reducers on steroids. However, in that specific sentence, the phrase: "if a transformer is given in list position"; I tend to presume that means replacing the list with a different object, which doesn't make sense. What am I missing?
Zubeyr Dereli
@dereli
Dec 04 2018 20:25
eventually those three are the same:
R.transduce(transducer, R.flip(R.append), [], numbers); //=> [2, 3]
R.into([], transducer, numbers); //=> [2, 3]
R.compose(R.reduce(R.flip(R.append), []), transducer)(numbers) //=> [2, 3]
Johnny Hauser
@m59peacemaker
Dec 04 2018 22:37
I'm watching a talk in which Conal Elliot says "It's really important that Time is reals, not something discrete, like integers." What is "reals"!?
These talks throw terms I can't find by googling at all.
Brad Compton (he/him)
@Bradcomp
Dec 04 2018 22:38
Probably Real Numbers
The important distinction is that integers are discrete, while reals are continuous (i.e can be divided infinitely)
Johnny Hauser
@m59peacemaker
Dec 04 2018 22:40
0.5 is not an integer?
Brad Compton (he/him)
@Bradcomp
Dec 04 2018 22:40
Nope!
Johnny Hauser
@m59peacemaker
Dec 04 2018 22:40
I think I'm stating the obvious, just making sure I get it
What a simple thing to say, but FP pros make it like alien science :)
Brad Compton (he/him)
@Bradcomp
Dec 04 2018 22:41

Functional programming combines the flexibility and power of abstract mathematics with the intuitive clarity of abstract mathematics.

- Randall Monroe

Stefano Vozza
@svozza
Dec 04 2018 22:42
Haha. i like that.