These are chat archives for ramda/ramda

6th
Mar 2017
Alexis De La Torre
@Alexis-De-La-Torre
Mar 06 2017 00:35
is there a function that remembers a value from the last pass?
Brad Compton (he/him)
@Bradcomp
Mar 06 2017 00:50
R.memoize
Brad Compton (he/him)
@Bradcomp
Mar 06 2017 00:50
Like that?
Alexis De La Torre
@Alexis-De-La-Torre
Mar 06 2017 01:14
i think so
let me try it
but how do i get the past value?
i want to use in a pipe
like:
add(2),
remembers(x, past  => x + past),
console.log
past would be the last return of that function
Alexis De La Torre
@Alexis-De-La-Torre
Mar 06 2017 01:42
i found R.scan but i think i will have to do it with a reactive library like most.js
Jonas Windey
@jonaswindey
Mar 06 2017 06:10
how could I rewrite the method monthByDefinition to use compose? I'm having issues sending the parameter to the map function separately.
const getValue = (definition, year, month, role) =>
  compose(
    Math.floor,
    parseFloat,
    pathOr(0, ['kpiData', definition, year, month, 'value'])
  )(role)

const monthByDefinition = (data, definition, year, month) =>
   sum(map(curry(getValue)(definition, year, month), data))
Keith Alexander
@kwijibo
Mar 06 2017 08:42
@Alexis-De-La-Torre something like this?
const stateAccum = reducer => accum => x => {
  accum = reducer(accum, x)
  return accum
}
const f = stateAccum(add)(1)
f(1) //=> 2
f(1) //=> 3
Stephan Meijer
@smeijer
Mar 06 2017 12:17

Is it possible to select a prop, with a fallback prop?

For example, when having a user object like below, I want to select the displayName, but fallback to username when displayName is undefined or empty.

const user = {
  username: 'Foo',
  displayName: 'Bar',
};

// looking for the Ramda way for
const getName = x =>  x.displayName || x.username;
Jonas Windey
@jonaswindey
Mar 06 2017 12:19
use defaultTo()
Stephan Meijer
@smeijer
Mar 06 2017 12:20
that was what I was thinking, but defaultTo already requires a simple type, isn't it? I cannot say defaultTo(R.prop('username')), and expect it to return the username.
Unless I do something like this; but that's really ugly:
const uname = R.defaultTo(R.prop('username'));
const dname = R.prop('displayName');
uname(dname(user))(user);
Jonas Windey
@jonaswindey
Mar 06 2017 12:25
looks like a case for compose()
Bravi
@Bravilogy
Mar 06 2017 12:25
@smeijer
const getName = compose(last, filter(Boolean), 
                    juxt([prop('username'), prop('displayName')]));
:D
Jonas Windey
@jonaswindey
Mar 06 2017 12:25
;)
Bravi
@Bravilogy
Mar 06 2017 12:26
probably too much but..
or maybe just
const getName = compose(head, filter(Boolean), props(['displayName', 'username']));
Stephan Meijer
@smeijer
Mar 06 2017 12:31
@Bravilogy , your my hero for today :grin: Thanks! The last snippet is perfect.
and OMG, I never have seen juxt before, what an awesome util :smile:
Bravi
@Bravilogy
Mar 06 2017 12:33
actually you could turn it into more dynamic function too. for example
const getFirst = compose(head, filter(Boolean), props);
getFirst(['displayName', 'username'], user);
this way you can pass any prop and any object
Stephan Meijer
@smeijer
Mar 06 2017 12:34
True, It's what I already did. Thanks to the Ramda repl. Also a big win over working with other utility belts.
Bravi
@Bravilogy
Mar 06 2017 12:34
yeah juxt is cool and so is useWith and converge
I've been using them lately
const getName = converge(or, [prop('displayName'), prop('username')]);
const getFirst = compose(apply(or), props);
:D
smaller version
Stephan Meijer
@smeijer
Mar 06 2017 12:42
const firstProp = curry(compose(apply(or), props));
const getName = firstProp(['displayName', 'username']);

getName(user)
Simply awesome. Thanks so much.
Stephan Meijer
@smeijer
Mar 06 2017 12:54
@xgrommx , code like that, makes me so happy that there is a repl. Where I can simply tryout stuff, and see the result :grin:
Galileo Sanchez
@galileopy
Mar 06 2017 13:00
how could I delay the evaluation of a function? fn = () => realFn(arg)?? realFn.bind(null, arg)??
Denis Stoyanov
@xgrommx
Mar 06 2017 13:04
@galileopy rx,most,promise,task?
Bravi
@Bravilogy
Mar 06 2017 13:23
@smeijer nice use of curry there
Jonas Windey
@jonaswindey
Mar 06 2017 14:05
how do you guys handle point-free notation when your functions have multiple arguments?
Bravi
@Bravilogy
Mar 06 2017 14:07
can u post an example?
Jonas Windey
@jonaswindey
Mar 06 2017 14:07
I'd like to prevent sending data and def again in the method monthByDefinition
Ideally I'd like the method to be
const monthByDefinition
  compose(
    sum,
    map(curry(kpiValue)(... here I need the second argument)),
 )
Vincent Orr
@Cmdv
Mar 06 2017 14:24

not sure how to do this one:

[{ id: 2324, stake: []},
 { id: 2366, stake: []},
 { id: 2398, stake: []},
 { id: 2322, stake: []}]

check matching id update it's stake

Denis Stoyanov
@xgrommx
Mar 06 2017 14:32
map?
map + lens or map + Object.assign
Denis Stoyanov
@xgrommx
Mar 06 2017 14:40
But, I'm not sure what u mean. source.map(x => x.id === 2366 ? over(lensProp('stake'), x => [10,...x], x) : x)
Vincent Orr
@Cmdv
Mar 06 2017 14:40
I need to return the whole array with updated stake thought @xgrommx
@xgrommx ohh thats perfect :)
I wasn't fully sure what lensProp did thank you :+1:
Denis Stoyanov
@xgrommx
Mar 06 2017 14:42
ok, also u can use ifElse for PF style
Vincent Orr
@Cmdv
Mar 06 2017 14:43
ah instead of the ? :
Denis Stoyanov
@xgrommx
Mar 06 2017 14:43
source.map(ifElse(compose(equals(2366), prop('id')), over(lensProp('stake'), x => [10,...x]), identity))
Daniel Skelton
@dskelton-r7
Mar 06 2017 14:43
Could you use an Either type for this scenario?
Denis Stoyanov
@xgrommx
Mar 06 2017 14:43
smth like
@dskelton-r7 what do u mean?
Vincent Orr
@Cmdv
Mar 06 2017 14:47
@xgrommx :+1:
Daniel Skelton
@dskelton-r7
Mar 06 2017 14:53
just instead of the ifElse? Put it into an Either.Right or Left then map over it?
Denis Stoyanov
@xgrommx
Mar 06 2017 14:54
if u need reason of rejection u can use Either but in case if u don't need reason u can use Maybe
for example, u can wrap try/catch and use monadic chain for computation
also exists Validation for accumulation your reasons with monoid :smile:
Daniel Skelton
@dskelton-r7
Mar 06 2017 14:56
Ahh, I thought of Either as it was validating something. id === 2366 for example. Instead of it being there. null or undefined
Denis Stoyanov
@xgrommx
Mar 06 2017 14:57
@dskelton-r7 this is id === 2366 boolean type
Daniel Skelton
@dskelton-r7
Mar 06 2017 14:57
yea
@xgrommx This validation? https://github.com/folktale/data.validation Have only used Either and Maybe. Need to check this out :D
Denis Stoyanov
@xgrommx
Mar 06 2017 15:07
yes
Either will be return Left on the first fail
but Validation accumulate them
Jonas Windey
@jonaswindey
Mar 06 2017 15:17
does anyone know how to handle point-free style with multiple function arguments? (line 28 of https://goo.gl/0eEhSU )
seems not clean to send the incoming arguments through
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:18
a quick way is to use keyword-argument style and pass an object insteadf @jonaswindey
but you'd need to deconstruct that object first of all in your composition and then you'd have to know how to pass in data and def to different steps in the pipeline
Anton Strömkvist
@ahstro
Mar 06 2017 15:20
Is there a function which takes a list of functions (f) and an argument(x) and applies each function to the argument, returning a list of the same length, with the results of f(x) for each f?
Jonas Windey
@jonaswindey
Mar 06 2017 15:20
that's what I tried, but then the map function always receives the full data too
which seems like a performance hit
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:20
Do you mean ap @ahstro ?
I know it's annoying @jonaswindey, but sometimes you have to give up on point-free if there's not an obvious way to do it :(
Anton Strömkvist
@ahstro
Mar 06 2017 15:23
@aaronmcadam Looks like both do the job, thanks!
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:24
juxt will just be sugar over ap anyways :)
converge is worth learning too @ahstro
Jonas Windey
@jonaswindey
Mar 06 2017 15:25
ok thanks anyway Aaron
Denis Stoyanov
@xgrommx
Mar 06 2017 15:25
@jonaswindey B1(sum)(map)
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:26
B1?
Anton Strömkvist
@ahstro
Mar 06 2017 15:27
@aaronmcadam Cool thanks! I can almost feel my brain growing :sweat_smile:
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:27
Look at @xgrommx's stuff, you'll explode :D
Denis Stoyanov
@xgrommx
Mar 06 2017 15:27
(sum .) . fmap => (...) = (.).(.) => b1 <=> (...) => sum ... fmap => b1(sum)(fmap)
Anton Strömkvist
@ahstro
Mar 06 2017 15:29
Thanks for the tip :)
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:29
I wish I could read those combinators :/
B is composition combinator
@aaronmcadam
// K :: a -> b -> a
const K = x => y => x;
// S :: (a -> b -> c) -> (a -> b) -> a -> c
const S = x => y => z => x(z)(y(z));
// I :: a -> a
const I = S(K)(K);
// I_ :: (a -> b) -> a -> b
const I_ = S(S(K));
// B :: (b -> c) -> (a -> b) -> a -> c
const B = S(K(S))(K);
// B1 ::
const B1 = B(B)(B);
// C :: (a -> b -> c) -> b -> a -> c
const C = S(B(B)(S))(K(K));
// W :: (a -> a -> b) -> a -> b
const W = S(S)(S(K));
// W__ :: (a -> b -> c -> c -> d) -> a -> b -> c -> d
const W__ = B(B(W));
// Q :: (a -> b) -> (b -> c) -> a -> c
const Q = C(B);

const MO = B1(W)(B);
const MO1 = B(B(W))(B);
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:31
Yeah, that's not really helping :D
is S sequence?
Denis Stoyanov
@xgrommx
Mar 06 2017 15:32
@aaronmcadam SK is basis =)
@aaronmcadam no, this is ap for function
S = ap
K = always
I = identity
I_ = apply
B = compose
C = flip
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:32
Where does this grammar come from?
Denis Stoyanov
@xgrommx
Mar 06 2017 15:33
W = join (monadic join)
Syaiful Bahri
@syaiful6
Mar 06 2017 15:33
@jonaswindey all you need to do, make your function take the data on last arguments. So, when combine it, you don't need to mention them..
Denis Stoyanov
@xgrommx
Mar 06 2017 15:33
@aaronmcadam Combinator Calculus =)
@aaronmcadam MO/MO1 = chain (monadic bind for function)
Aaron Mc Adam
@aaronmcadam
Mar 06 2017 15:35
Thanks :)
Syaiful Bahri
@syaiful6
Mar 06 2017 15:35
@jonaswindey since, Ramda compose allow the right most function have any arity, you can take advantage of it. For example, clean up your code, it become like this: https://goo.gl/tgywhD
Denis Stoyanov
@xgrommx
Mar 06 2017 15:36
@syaiful6 it work only for first function of composition =)
Syaiful Bahri
@syaiful6
Mar 06 2017 15:42
@xgrommx yes, just keep in mind that.
Denis Stoyanov
@xgrommx
Mar 06 2017 15:44
I think it isn't correct) arity should be only 1
Syaiful Bahri
@syaiful6
Mar 06 2017 15:51
I don't know what you mean, Ramda allow it, so we can just take advantage of it. It probably more practical in js. Like your B1(sum)(map), essentially same as compose(sum, map) in Ramda perspective. So, just take advantage of it. This is not Haskell anyway.
Jonas Windey
@jonaswindey
Mar 06 2017 16:13
hmm thanks @syaiful6 , very interesting
Rick Medina
@rickmed
Mar 06 2017 16:26
for the ones who use compose (vs pipe), why do you like it? it breaks reading and writing flow (as reading in english)
Bravi
@Bravilogy
Mar 06 2017 16:27
@smeijer here's another solution, which supports n number of props and not just two:
const firstProp = curry(compose(reduce(or, ''), props));
and then
const getNameDynamic = firstProp(['firstName', 'username', 'someOtherName', 'andYetAnotherName']);
will always get the first not null|undefined value
Stephan Meijer
@smeijer
Mar 06 2017 16:31
@Bravilogy , that one is so awesome, that it should become part of the core.
Bravi
@Bravilogy
Mar 06 2017 16:33
lol :D
ramda is awesome and it should become a core of js
Stephan Meijer
@smeijer
Mar 06 2017 16:33
amen to that
Brad Compton (he/him)
@Bradcomp
Mar 06 2017 16:34
@rickmed I use both. Generally I use compose if it's a single line composition. It makes visual sense (to me) to consider the data being passed through from right to left:
compose(f, g, h)(x);
compose(f, g)(h(x));
compose(f)(g(h(x)));
f(g(h(x))));
Rick Medina
@rickmed
Mar 06 2017 17:02
@Bradcomp :thumbsup: we have different styles :)
Stefano Vozza
@svozza
Mar 06 2017 17:04
yeah, if it's all on one line i like to use compose as it mirrors the execution, i.e., the values progress from the inside out
Keith Alexander
@kwijibo
Mar 06 2017 17:06
I used to do it like that (and still like that style fine) but these days just use pipe for everything - i find it lowers the mental overhead of concepts you need, to understand a given bit of code
Keith Alexander
@kwijibo
Mar 06 2017 17:22
The Sanctuary API is interesting here: S.compose only takes 2 functions, enforcing minimal R-L composition
S.pipe takes an array of functions
actually where I do still use compose, is when doing combinator type things
with 2 functions
Robert Mennell
@skatcat31
Mar 06 2017 17:26

@Bravilogy

ramda is awesome and it should become a core of js

I'd rather not. My realtime metrics would be hosed. I routinely see arrays of 10k+

Bravi
@Bravilogy
Mar 06 2017 17:28
@skatcat31 you should use transducers then :D
Robert Mennell
@skatcat31
Mar 06 2017 17:32
I do. They're still too slow for arrays of that size and breadth. After all timeouts due to array traversal are traverse-ities
Some of my work falls in the realm of 'Actually has to write for loops for performance reasons'
and 'has to try and use byte optomized js'
in which case I often wonder why I don't just write my code in C/++... and then I remember why I hate that language..
Robert Mennell
@skatcat31
Mar 06 2017 17:40
Now I'll say this much, there are some features of Ramda that I wish DID exist in core JS
mainly compose and pipe
Bravi
@Bravilogy
Mar 06 2017 17:44
@skatcat31 tbh I've never had any issues with performance. I guess I don't work with a huuuuuge amount of data
I've worked with a few thousands of records but..
I kinda think that if front end has to deal with such amount of data that affects performance, then the problem is in the backend. Or in other words, how the application is structured
I might be wrong
Stephan Meijer
@smeijer
Mar 06 2017 17:47
@Bravilogy , even in the front-end it doesn't need to be a problem. Depends on how the data is being visualized / rendered.
Keith Alexander
@kwijibo
Mar 06 2017 17:47
in some cases probably, but there are legitimate trade-offs you might want to make with handling large amounts of data in the client
Stephan Meijer
@smeijer
Mar 06 2017 17:47
Simple calculations of course depend on the target platform. When sending huge amounts of data to smartphones, I totally agree with you. It should be solved on the backend.
Robert Mennell
@skatcat31
Mar 06 2017 17:48
this is on the backend.
hence why I mentioned not writing it in C/++
Rick Medina
@rickmed
Mar 06 2017 17:56
@skatcat31 do you have an example of the transducer bottleneck where the manual loop solved it? I guess it had to be in the breadth processing, no?
Robert Mennell
@skatcat31
Mar 06 2017 17:59
@rickmed real time power analytics over a years worth of data. 31,557,600 results per set, 548 sets = 17,293,564,800 results to reduce
Rick Medina
@rickmed
Mar 06 2017 18:07
I was just curious where was that big of a performance difference in js code where the timeout was avoided
@skatcat31
Robert Mennell
@skatcat31
Mar 06 2017 18:21
That last sentence isn't making to much sense ot me?
@rickmed
Rick Medina
@rickmed
Mar 06 2017 18:26
@skatcat31 you mentioned even transducers failed to avoid timeouts so you needed to refactor to manual loops?
Robert Mennell
@skatcat31
Mar 06 2017 18:33
@rickmed I think I'm using timeouts here and it's getting confused with network timeouts, not realistic time to opperate.
I really amde that joke more for the sake of the pun...
Brad Compton (he/him)
@Bradcomp
Mar 06 2017 18:36
@skatcat31 I caught the pun and appreciated it :stuck_out_tongue:
Robert Mennell
@skatcat31
Mar 06 2017 18:40
@Bradcomp thanks. @rickmed several hundred GB of data, each point a collection, collectceptions need to be reduced into other collectceptionceptions. Eventual output data size: 1.2 TB
we ran into other overheads
do I like writing unrolled, byte optomized loops? hell no. did I have to in this case? sadly...
Rick Medina
@rickmed
Mar 06 2017 18:43
@skatcat31 my bad! I, admittedly, have dm +1 people to explain me puns :stuck_out_tongue_closed_eyes:
Robert Mennell
@skatcat31
Mar 06 2017 18:50
@rickmed all good. As you can see I like puns too. Either way in this case, overhead was a huge problem. As much as could be trimmed out, was trimmed out.
Raine Virta
@raine
Mar 06 2017 19:08
R.ascend
Nate Shoemaker
@nshoes
Mar 06 2017 19:11
that's a useful bot :]
Denis Stoyanov
@xgrommx
Mar 06 2017 19:16
But lambda bot more powerful :)
Jon Gold
@jongold
Mar 06 2017 19:41
what Either / Maybes are people using? so many options, I have no idea what the current consensus is
Brad Compton (he/him)
@Bradcomp
Mar 06 2017 19:46
Sanctuary if you want the run time type checker. The old Folktale modules otherwise
Jon Gold
@jongold
Mar 06 2017 19:49
yeaaaah I think putting Sanctuary in is a bigger battle than I want right now, thanks
Gabe Johnson
@gabejohnson
Mar 06 2017 20:18
@jongold you can turn off the type checking in Sanctuary and then just use it as you would Ramda
Markus Pfundstein
@MarkusPfundstein
Mar 06 2017 21:17

@xgrommx

S = ap
you should put this info in the comments

if you put this info in the comments
you would enlighten us a lot ;-)
oh and do it please for all combinators
Denis Stoyanov
@xgrommx
Mar 06 2017 21:31
Markus Pfundstein
@MarkusPfundstein
Mar 06 2017 21:31
oh sry, nvmd
Julio Borja Barra
@juboba
Mar 06 2017 22:04
@ram-bot R.map(x => x*x, [1, 2, 3, 4])
Robert Mennell
@skatcat31
Mar 06 2017 22:05
@ram-bot R.map(x => x*x, [1, 2, 3, 4])
ram-bot
@ram-bot
Mar 06 2017 22:05
[ 1, 4, 9, 16 ]
Robert Mennell
@skatcat31
Mar 06 2017 22:05
don't forget your '`'s
Julio Borja Barra
@juboba
Mar 06 2017 22:05
ohh
thanks
Xavier Via
@xaviervia
Mar 06 2017 22:33
Hi!
I just wanted to ask if any of you know what the status of ramda/ramda#1959 is
I don’t mind about the PR specifically being merged or not, but many of my colleagues are interested in knowing whether the path for importing ramda modules are going to be updated :)
I know that some will be more comfortable using the individual files if they would be exposed in ramda/functionName instead of ramda/src/functionName, since the former seems like an official API and the latter looks more like “reaching in” into private APIs
Galileo Sanchez
@galileopy
Mar 06 2017 23:12
When you work with structured data, do you often use daggy or something of sorts to give your structured data a name?
or just transform and use data as it comes, without worrying about having a spec for the intended structure of your data?
I was pretty much just using data without taking the time to think, if it would have been more readable if the data was structured and documented somewhere in the code