These are chat archives for ramda/ramda

7th
Apr 2017
Vesa Karvonen
@polytypic
Apr 07 2017 00:02

@jonahx A basic way is to use scan, tail and map.

Here is challenge: Do the same kind of numbering for the non-array values in an arbitrarily nested data structure of arrays such that the result is a data structure of the same shape, but with each non-array element replaced by the count at that point (in-order). For example:

// #=> [1, [[2, 1], 1], 2, [3, [[4]], [3, 4]], 5]  <—input data structure
// #=> [1, [[1, 2], 3], 2, [1, [[1]], [2, 2]], 1] <— returned data structure: previous appearance counts for each element
Johnny Hauser
@m59peacemaker
Apr 07 2017 00:05
@Papipo Nice job! I wonder if someone can code golf it into point free :)
Rodrigo Álvarez
@Papipo
Apr 07 2017 00:06
@polytypic what do you think about my implementation?
const sample = [1, 2, 1, 1, 2, 3, 4, 3, 4, 5]

const counts = addIndex(map)(
  (x, index, list) => pipe(
    slice(0, inc(index)),
    filter(equals(x)),
    length,
  )(list)
)
Thanks @m59peacemaker
Given I've discovered ramda like two days ago, this feels good XD
Johnny Hauser
@m59peacemaker
Apr 07 2017 00:06
Wow! That's amazing, man.
I've been using it a while and I'm wretched at it.
But to be practical, I'd do that the imperative way and put it on npm
Rodrigo Álvarez
@Papipo
Apr 07 2017 00:09
Although scan might be a better approach. Seems made for it.
(I just didn't knew it even existed)
Johnny Hauser
@m59peacemaker
Apr 07 2017 00:11
Scan is similar to reduce, but returns a list of successively reduced values from the left
WUT
looking at the source code is often easier than reading descriptions of this stuff
Rodrigo Álvarez
@Papipo
Apr 07 2017 00:13
yeah
It always yields a list of length + 1 elements
Anyway, it's 2 am here already. Bed time!
Jonah
@jonahx
Apr 07 2017 00:19
@polytypic yeah, that’s how i did it with ramda, but i did not feel the result was as clean as the imperative approach.
@Papipo yours is close, but still a bit more complex imo. also, i forget if it was @davidchambers or @JAForbes, but one of them convinced me not to use addIndex. there’s generally a more ramda-ish solution available without it. in this case, scan, as others noted, though tbh in this case i like your solution better than what i was able to do with scan.
Rafi
@Rafi993
Apr 07 2017 07:39
HI
Matt McKellar-Spence
@MattMS
Apr 07 2017 07:47
:wave:
Piotr Nowak
@pnowak2
Apr 07 2017 07:59
there's bug in documentation for .where() function. should be replaced with R. :) just noticed.

describe('.where() - Takes a spec object and a test object; returns true if the test satisfies the spec. Each of the specs own properties must be a predicate function. Each predicate is applied to the value of the corresponding property of the test object. where returns true if all the predicates return true, false otherwise.', () => {
it('should return true if object looks like spec says', () => {
var pred = R.where({
a: R.equals('foo'),
b: R.complement(R.equals('bar')),
x: R.gt(R., 10),
y: R.lt(R.
, 20)
});

  var r1 = pred({ a: 'foo', b: 'xxx', x: 11, y: 19 });
  var r2 = pred({ a: 'xxx', b: 'xxx', x: 11, y: 19 });

  expect(r1).to.be.true;
  expect(r2).to.be.false;
});

});

Matt McKellar-Spence
@MattMS
Apr 07 2017 08:43
@pnowak2 ^
Rafi
@Rafi993
Apr 07 2017 08:50
I am trying to take deep difference between objects ? is there any method to do so. Thanks in advance :)
Matt McKellar-Spence
@MattMS
Apr 07 2017 09:37
@Rafi993 have you looked at R.difference? http://ramdajs.com/docs/#difference
Rafi
@Rafi993
Apr 07 2017 09:43
yes @MattMS but it does seems to take deep difference between objects
I need to Get the structural differences between two objects.
Kurt Milam
@kurtmilam
Apr 07 2017 09:44
@polytypic I'll be happy to show you what I come up with, but I expect it to be underwhelming :D
I'm working with a number of new concepts (lenses, atoms, streams) and libraries (mithril), so it's a real learning experience for me. I'm also very tempted to just switch over to calmm, especially since I noticed that you plan to add support for react native.
Kurt Milam
@kurtmilam
Apr 07 2017 09:51
The eventual target for whatever framework I end up using is a mashup of a CRM and estimation tool targeted to companies operating in a few specific construction industries. It will involve porting over an existing, in-use browser-based estimation tool that I started writing back in 2010 using jQuery and underscore. The tool includes some SVG-based 'drafting' functions and is painful to modify or extend in its current state.
Vesa Karvonen
@polytypic
Apr 07 2017 10:06
@kurtmilam I'm not looking to be impressed, but rather to see if I could give advice or learn about difficulties that I might want to address in Calmm documentation or libraries.
Kurt Milam
@kurtmilam
Apr 07 2017 10:13
:thumbsup:
Vesa Karvonen
@polytypic
Apr 07 2017 12:15
@jonahx https://github.com/calmm-js/partial.lenses/#L-traverse - A solution to the numbering challenge I mentioned. Just replace L.elems with flatten to manipulate nested arrays.
Johnny Hauser
@m59peacemaker
Apr 07 2017 14:28
I'm not familiar with calmm and don't have time to absorb it right now... just looking it over quickly, I think of cycle and recycle.
Jonah
@jonahx
Apr 07 2017 14:50
@polytypic thanks i'll take a look later
Bravi
@Bravilogy
Apr 07 2017 14:52
it's not very clear what Reader does from ramda-fantasy. Could anyone shed some light please?
Matthew Willhite
@miwillhite
Apr 07 2017 14:54
Bravi
@Bravilogy
Apr 07 2017 14:57
yay Mr Boolean a saviour :D
thank you!
Matthew Willhite
@miwillhite
Apr 07 2017 15:01
@Bravilogy I should note…I think the ramda-fantasy Reader uses a different API than what is shown here…but you should be able to draw some parallels by comparing the source to fantasy-readers
Johnny Hauser
@m59peacemaker
Apr 07 2017 15:10
I don't get it
what's the difference between having a function that returns result on which you can do result.run(database) vs having a function that returns a function that takes database result(database) ?
It looked to me like he made the code more complicated for no benefit (I'm sure there is one... I'm just not seeing it)
to be more clear, I see that he proposed the situation where he didn't have access to that global database and that's the problem being solved. But he could have solved it by making a function that returns a function that takes database
Raine Virta
@raine
Apr 07 2017 15:17
@m59peacemaker good question
I guess the question is why use Reader newtype (which essentially wraps (-> r)) instead of plain function
Matthew Willhite
@miwillhite
Apr 07 2017 15:27

@m59peacemaker:

You can think of this in much of the same way as how a function has access to arguments that are provided by the caller of the function. In fact, the Reader type is effectively a wrapper type around a function to provide the various monad and functor instances.

Johnny Hauser
@m59peacemaker
Apr 07 2017 15:28
Sure, but the big question is "why?"
map(), chain(), map(), Reader.of doesn't appeal to me over (database) => {}
Matthew Willhite
@miwillhite
Apr 07 2017 15:29

I can’t say I have the answer to that…I’ve never used Reader.

But I am inclined to think it has something to do with the compositionality…

Think about what all those maps and chains contain…individual, multi-purpose functions
they are exposed. Whereas in your function they are in a black pit
What if you could represent your entire application at a high level using maps and chains? The developer can see every step at a glance. Whereas when you have those functions hidden inside of another function, the dev has to start digging just to get an idea of the sequence of actions taken on database
Matthew Willhite
@miwillhite
Apr 07 2017 15:35
In other words:
(database) => {} tells me absolutely nothing about what is happening
map(c), chain(b), map(a), Reader.of tells me that a, b, and c are what my application is comprised of
I’m sure there is much more to it than that
Rick Medina
@rickmed
Apr 07 2017 15:52
Reader favors composition. You could create a partially applied function with db but then you would have to pass it down through all the functions that doesn't care about until the one who does. Or through a closure which would be sort of a local global. Reader passes the data implicitly which you can access arbitrarily
just as i see it anyways
Johnny Hauser
@m59peacemaker
Apr 07 2017 16:01
In that example, ask.map is depending on this isn't it?
oh wait, nm
So, where you'd normally have a big closure / series of closures passing a var around to get a value to a computation deep within, instead you can have that computation return ask.map(fn) and it will get that value
Rick Medina
@rickmed
Apr 07 2017 16:05
yes, passed as arg to fn
Rick Medina
@rickmed
Apr 07 2017 16:10
I find needing to flip the fn passed to reduce fairly often, I'm sure it has been discussed here, can someone remind me why is the current arg order?
Gabe Johnson
@gabejohnson
Apr 07 2017 16:26
@rickmed do you usually want the same init value?
which is the most stable argument in your usage?
Rick Medina
@rickmed
Apr 07 2017 16:26
I mean the accumulation function
Gabe Johnson
@gabejohnson
Apr 07 2017 16:27
ohhh
Gabe Johnson
@gabejohnson
Apr 07 2017 16:32
@rickmed I'm guessing a combination of a couple of things
JS native reduce has that order
and that order plays nice w/ concat and subtract
though I've argued that the arg order for those functions is backward
they're ordered like operators
Rick Medina
@rickmed
Apr 07 2017 16:38

though I've argued that the arg order for those functions is backward

@gabejohnson I tend to agree. Although, I feel I've discussed this previously and there is a strong argument to the alternative but I can't remember -eg: reduceRight's args are inverted.

Gabe Johnson
@gabejohnson
Apr 07 2017 16:40
ramda/ramda#1497
For a little light reading
Rick Medina
@rickmed
Apr 07 2017 16:42
@gabejohnson right! is also about the relationship with the api of the other fns not necessarily reduce itself. thanks!
yeah, I've read that discussion previously
Gabe Johnson
@gabejohnson
Apr 07 2017 16:43
I find myself having to flip w/ reduce too
Johnny Hauser
@m59peacemaker
Apr 07 2017 18:10
Did I read correctly in there that using reduceRight is the solution?
That doesn't make sense to me
Gabe Johnson
@gabejohnson
Apr 07 2017 18:15
@m59peacemaker no. @rickmed was just saying that the arg order is reversed for reduceRight
Which makes sense visually
but not functionally
Robert Mennell
@skatcat31
Apr 07 2017 18:27

@gabejohnson :point_up: April 7, 2017 9:40 AM I look at this and I can only think it was designed in this way to match syntactical and preference. It makes me wonder why they wouldn't just do one of the following for their functions:

// gt(test, predicate): gt(5,6) === false
// ( test > predicate )
var gt5 = gt(_,5);
var gt6 = flip(gt)(6);

After all Ramda is designed in the fn(known, given) structure, and adhering to a common API is what makes a library go from decent or even good to ubiquitous

although it's really funny for me that
var gt5 = lt(5)
Gabe Johnson
@gabejohnson
Apr 07 2017 18:33
@skatcat31 but your example shows the inconsistency (lack of common API) when it comes to the comparators.
If they're going to be curried, they should be reversed
If they're meant to be used as operators they shouldn't be curried
Robert Mennell
@skatcat31
Apr 07 2017 18:36
@gabejohnson I feel like that argument may be a logical fallicy for the fact that people are assuming that a comparitor should automaticaly reverse, instead of realizing a reversed comparitor is simply it's inverse(binary reverse is inverse, no?)
@gabejohnson especially since L->R composition and ingestion is kind of the norm it stands that 5 gt 6 in infix would be eqwuivilant to gt(5,6) in suffix
It seems to me that people's logic is going against the very well documented api of Ramda?
Gabe Johnson
@gabejohnson
Apr 07 2017 18:40
Even the authors of ramda disagree on this topic
Robert Mennell
@skatcat31
Apr 07 2017 18:47
I've noticed. One of the big arguments is logical versus source I keep seeing:
"gt(5,x) == 5 < x since it makes logical sense" <- logical fallacy since source is functional programming paradimes with infix grammar: 5 gt x
also when spoken: "greater than 5 is 6"... That's some Yoda grammer. Going back to infix source though we get "is 5 greater than 6?" so it's more of people thinking in terms of Yoda's wisdom than thinking in terms of FP. "We want it this way" vs "we designed it from this this way" thinking
Ontop of that this change would be breaking
I like to kind of think of it in terms of concat: concat('5', '> ', '6') seems close to a function like flip(concat)('>')(5,6), but that's probably a little TOO obtuse?
Gabe Johnson
@gabejohnson
Apr 07 2017 18:51
I think concat is backward as well
Robert Mennell
@skatcat31
Apr 07 2017 18:51
How so?
Gabe Johnson
@gabejohnson
Apr 07 2017 18:53
var concatABC = concat('ABC');
concatABC('DEF'); // I expect 'DEFABC'
This may just be the way I think of concatenation though
Johnny Hauser
@m59peacemaker
Apr 07 2017 18:54
I thought the same
Robert Mennell
@skatcat31
Apr 07 2017 18:57
This is the way I think of it:
@ram-bot const infix = (a, fn, b) => fn(a,b); infix(5,gt,6);
and
const concatToABC = concat('ABC') since I'm thinking of known and what I'm attaching to it. I tend to think the RamdaJS API is defined as "Take the known, and operate on it with the unknown", which when applied to the API seems consistent to me even on the opperators
Johnny Hauser
@m59peacemaker
Apr 07 2017 18:57
There's the thing being added and the thing being added onto.
Robert Mennell
@skatcat31
Apr 07 2017 18:57
I confused ram-bot didn't i?
Johnny Hauser
@m59peacemaker
Apr 07 2017 18:57
the thing being added onto is the last argument in most cases
and the thing being added is the first
concat('ABC') says to me "add abc to the thing"
Gabe Johnson
@gabejohnson
Apr 07 2017 18:58
var appendABC = append('ABC');
appendABC('DEF'); // actual -> ['D', 'E', 'F', 'ABC']
Johnny Hauser
@m59peacemaker
Apr 07 2017 18:58
exactly
Robert Mennell
@skatcat31
Apr 07 2017 18:59
what you guys are describing as how concat should work seems more to me like how an appendStr method should work
Johnny Hauser
@m59peacemaker
Apr 07 2017 19:00
@ram-bot [ 'a', 'b', 'c' ].concat([ 'd', 'e', 'f' ])
ram-bot
@ram-bot
Apr 07 2017 19:00
missing ) after argument list
Johnny Hauser
@m59peacemaker
Apr 07 2017 19:00
doh
Robert Mennell
@skatcat31
Apr 07 2017 19:00
right, infix
Johnny Hauser
@m59peacemaker
Apr 07 2017 19:01
concat(a, b) in that case
that's what Ramda is doing
Gabe Johnson
@gabejohnson
Apr 07 2017 19:01
@ram-bot [ 'a', 'b', 'c' ].concat([ 'd', 'e', 'f' ])
ram-bot
@ram-bot
Apr 07 2017 19:01
[ 'a', 'b', 'c', 'd', 'e', 'f' ]
Robert Mennell
@skatcat31
Apr 07 2017 19:01
concat(a,b) however is suffix, which when converted to infix becomes a concat b
Gabe Johnson
@gabejohnson
Apr 07 2017 19:02
in most cases ramda takes this and passes it as the last argument
Johnny Hauser
@m59peacemaker
Apr 07 2017 19:02
If regular JS is concat(a, b) then I'd think Ramda would be concat(b, a)
just like a.map(fn) is not map(a, fn)
Gabe Johnson
@gabejohnson
Apr 07 2017 19:03
there is a lack of consistency
Robert Mennell
@skatcat31
Apr 07 2017 19:04
a is an object, map is a property.. that's not functional composition but imperitive isn't it?
... I feel like I'm trying to compare cunquats to radiators XD
Gabe Johnson
@gabejohnson
Apr 07 2017 19:07
map is a function attached to a property
you call it like this map.call(a, fn) :wink:
But that's no good for composition
Ramda does map(fn, a) and concat(a, b)
Robert Mennell
@skatcat31
Apr 07 2017 19:10
I read that as Ramda does map(known, unknown) and concat(known, unknown)
since often time you will always know what function you want to call with map on somethign supplied(since a function must be declared BEFORE an object can use it, thus it is known)
Gabe Johnson
@gabejohnson
Apr 07 2017 19:11
Known to you, not me
and I know which list I want to concatenate with another list
there is no correct answer here
it's a matter of expectation and opinion
Robert Mennell
@skatcat31
Apr 07 2017 19:13

there is no correct answer here
it's a matter of expectation and opinion

:+1:

Gabe Johnson
@gabejohnson
Apr 07 2017 19:13
Happy Friday!
Robert Mennell
@skatcat31
Apr 07 2017 19:15
@gabejohnson I feel like there are going to be two primary camps on this: known infix unknown and order of supplication(order of asking)
if we go by order of asking, I totally agree, opperators are completely busted
I also feel like we just ranted the entire thread we quoted back into the chat XD
Rick Medina
@rickmed
Apr 07 2017 19:20
@gabejohnson happy friday!

I also feel like we just ranted the entire thread we quoted back into the chat XD

what's wrong about that? :)

Johnny Hauser
@m59peacemaker
Apr 07 2017 19:31
heheh
awb99
@awb99
Apr 07 2017 19:43
hi!
I am trying to assemble a "merge" operation with Ramda.
I somehow cannot get it done to my requirement
I am trying to merge the result of two database query results,
any ideas?
Johnny Hauser
@m59peacemaker
Apr 07 2017 20:14
yep, just a sec
Johnny Hauser
@m59peacemaker
Apr 07 2017 20:19
@awb99
pipe(
  concat,
  groupBy(R.prop('date')),
  map(mergeAll),
  values
)(a, b)
oops, I got them out of order though
Johnny Hauser
@m59peacemaker
Apr 07 2017 20:26
pipe(
  concat,
  groupBy(R.prop('date')),
  map(mergeAll),
  values,
  sort((a, b) => new Date(a.date) - new Date(b.date))
)(a, b)
awb99
@awb99
Apr 07 2017 21:05
@m59peacemaker 1000 thanks! this is a cool solution!!!!
Robert Mennell
@skatcat31
Apr 07 2017 21:08
@m59peacemaker oddilly enough that helps me out too. Thanks!
Rick Medina
@rickmed
Apr 07 2017 21:19
@m59peacemaker #teampipe :sunglasses:
Johnny Hauser
@m59peacemaker
Apr 07 2017 21:20
woah man. Neat. I normally suck at everything :)
Robert Mennell
@skatcat31
Apr 07 2017 23:03
I can't believe I've just now needed to, for the first time in this code base, write a function to delay setting a timeout...
Rick Medina
@rickmed
Apr 07 2017 23:14
@skatcat31 why does it surprises you?
Robert Mennell
@skatcat31
Apr 07 2017 23:16
@rickmed because it's the first time I've written one in 2.2 million lines of code... I have yet to have actually needed to delay setting a timeout unti la function was called. I program realtime interactions pages and libraries that you would think would constantly want a way to delay polling. Nope, first time I've had to write one
Rick Medina
@rickmed
Apr 07 2017 23:20
2.2 million of js? can you provide a bit of context? :)
@skatcat31
Robert Mennell
@skatcat31
Apr 07 2017 23:23
@rickmed we write software mostly in Node/JS. This includes Database interaction, REST APIs, APIs, front end logic, layouts, dynamic content, and fetch functions. We are working on real time power analytics. I have just now, for the first time, written a function to lazily set a timeout. We have other pages that poll based on interval. this is the only implied interval page we have so far and it's only because this is the first time we need an interval with ever changing behaviour
Rick Medina
@rickmed
Apr 07 2017 23:28
@skatcat31 may I ask which db do you use for real time? is it plain js or typescript? if not, have you considered ts/flow?
Robert Mennell
@skatcat31
Apr 07 2017 23:29
@rickmed the DB isn't where i'm interacting. This is currently interacting with an API. The DB we use is postgresql through pg-promise(I'm a constant in that room too)
as for in memory states(in memory databases) we've done that a few times, but we try to avoid it
Johnny Hauser
@m59peacemaker
Apr 07 2017 23:38
You have personally written 2 million LoC?
While lines of code is a totally unstable metric, that seems to be 50 - 100 years of work
Rick Medina
@rickmed
Apr 07 2017 23:40
well, to be fair @skatcat31 hasn't disclosed his age
Robert Mennell
@skatcat31
Apr 07 2017 23:41
XD
Johnny Hauser
@m59peacemaker
Apr 07 2017 23:41
I'm assuming there is some tradeoff between 50 - 100 employees and 1 year of labor or 1 employee with 50 - 100 years of labor at play here :)
Robert Mennell
@skatcat31
Apr 07 2017 23:42
TBF I said in 2.2 million lines of code, that can be taken many ways. This is "Inside of a library consisting of 2.2... I have jsut for hte first itme in the library"
Robert Mennell
@skatcat31
Apr 07 2017 23:56
which when you look at it that way is not so impressive, but is sitll kind of mind bending I've not seen it done before