by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Jan 31 2019 22:17
    CrossEye commented #2779
  • Jan 31 2019 21:04
    ArturAralin commented #2779
  • Jan 31 2019 20:08
    CrossEye commented #2779
  • Jan 31 2019 18:56
    buzzdecafe commented #2631
  • Jan 31 2019 18:09
    ArturAralin commented #2779
  • Jan 31 2019 16:18
    CrossEye commented #2779
  • Jan 31 2019 16:10
    CrossEye commented #2631
  • Jan 31 2019 16:06
    CrossEye commented #2777
  • Jan 31 2019 14:44
    ArturAralin opened #2779
  • Jan 31 2019 07:39
    inferusvv commented #2631
  • Jan 31 2019 03:07
    sespinozj commented #2771
  • Jan 31 2019 02:33
    machad0 commented #2771
  • Jan 31 2019 02:26
    JeffreyChan commented #2777
  • Jan 30 2019 14:30
    CrossEye closed #2777
  • Jan 30 2019 12:13
    vanyadymousky updated the wiki
  • Jan 30 2019 01:42
    JeffreyChan commented #2777
  • Jan 29 2019 21:06
    vanyadymousky updated the wiki
  • Jan 29 2019 16:28
    CrossEye commented #2777
  • Jan 29 2019 15:50
    mbostock commented #2772
  • Jan 29 2019 15:48
    CrossEye commented #2772
Brad Compton (he/him)
@Bradcomp
You can use them in a fairly non-FP codebase. Function returns an Array or undefined - use Maybe. Need to return error results from a function - use Either. Once the value of those are established bringing in Futures will be a bit easier.
Ben Briggs
@ben-eb
Thanks @Bradcomp :) Yes, DI is a pain point right now. Personally I like hiding things like vendor SDKs inside a closure so it makes testing units easier, but I think this adds too much complexity when the same result could be done by using structures such as Future and composition rather than injection.
I don't think pointfree necessarily is adding pain, the problem seems to be in the amount of passing around functions, and because some of these functions have to handle side effects we end up with a lot of (arg1, arg2) => async () => { ... }
Ben Briggs
@ben-eb
But now we have some complex DI code maybe it can be a good selling point for using ADTs instead? Personally am already sold on the benefits of these things but as we know everyone is on their own code journey :slight_smile:
Ben Briggs
@ben-eb
I am working on some material about taking imperative code into functional and extending that into ADTs when the requirements change. e.g. start with input as always a string, then we add null, then we add a string of a different shape, and contrasting the approaches on a very small unit of code.
So for instance one pattern you might use in imperative is early return, but that doesn't compose well (which is when you might reach for Maybe)
Brad Compton (he/him)
@Bradcomp
I was gonna say, starting small can help. Show how to deal with a bunch of if statements using Maybe or Either. Show how currying a single function can give you a bunch of different functions. The place I think currying really helps is if you need to partially apply a function against an array of values (think vectors and the like)
Ben Briggs
@ben-eb
Doing stuff with lift and curried functions I find to be very readable rather than the nested loops
Brad Compton (he/him)
@Bradcomp
Only if you have a good understanding of how lift works up front though
or good examples
But yeah, ap is a great use case for curry except that it relies on the understanding of uh... container types
Ben Briggs
@ben-eb
To be fair we haven't really done much list comprehension type stuff. A lot of it is gluing vendor code together - lot of aws sdk and reshaping data from third parties
Brad Compton (he/him)
@Bradcomp
reshaping data is the bread and butter of Ramda IMO
Ben Briggs
@ben-eb
Exactly. That stuff is where pure functions really shine
Brad Compton (he/him)
@Bradcomp
One way to attack it would be to position Ramda as a DSL for data manipulation, and show how it can make weird imperative functions disappear into readable pipelines.
Ben Briggs
@ben-eb
I've introduced ramda to only a couple people, our main is lodash/fp right now. I'd like to change that of course :)
Both times I've taken some anonymous lambda and wrapped a ramda function around it, then progressively refactor it until it's fully declarative
const f = when(x => x === 2, x => x + 1);
const f = when(eq(2), x => x + 1);
const f = when(eq(2), inc);
for instance
But both ramda & lodash offer good stories for data manipulation
Brad Compton (he/him)
@Bradcomp
true
Ben Briggs
@ben-eb
Ohh sorry it's equals isn't it. lodash is eq :D
Brad Compton (he/him)
@Bradcomp
groupBy is one of my favorites in that it does exactly what it sounds like, it's not trivial (though not too complicated either), and it is often really helpful
Ben Briggs
@ben-eb
I'm not sure I have a favourite ramda function! What is unique about it for me is that it's a large api surface which I have used a majority of, not like a lot of libraries where you need only a handful of things
Brad Compton (he/him)
@Bradcomp
I just mean it's a good one for demonstrating value
Ben Briggs
@ben-eb
Oh I know. It's reject because of the ergonomics of it - filter(x => x !== 'foo') => reject(x => x === 'foo') - same goes for complement. Too many times writing two predicates instead of one plus complement(one)
Brad Compton (he/him)
@Bradcomp
Also, map is nice in that it works on Objects and returns the same typeclass as it receives.
Ben Briggs
@ben-eb
I think I remember ruby had the same DX
Yup, ruby has select and reject. I really liked it at the time
map is also nice - lodash has mapValues which I like less
Pierre-Antoine Mills
@pirix-gh
what do you guys think of this? https://github.com/selfrefactor/rambda
Pierre-Antoine Mills
@pirix-gh
the project owner claims overall 70% better performance compared to ramda... not sure how the tests are done anyway, and it does not seem to handle placeholders either
Gezim Hoxha
@HappyGezim_twitter
Trying to see if this can be done more simply:
const filtersFromUniqueIds = (items: SelectedRecipeFilter[], ids: string[]) => {
  return items.filter(item => includes(item.uniqueId, ids));
};
Ben Briggs
@ben-eb
@HappyGezim_twitter R.propSatisfies ?
Twizzes
@Twizzes
@HappyGezim_twitter I I couldn't really think of a way to make it simpler, per se. But you can make it more modular(?) - I'm not too sure this is even true. I guess looking at this might spark some ideas for you, though:
const recipes = [{ uniqueId: 5 }, { uniqueId: 2 }, { uniqueId: 10 }];
const ids = [2, 5, 6, 1];

const _includes = keepers => item => R.includes(item, keepers);
const keepIds = _includes(ids);

const res = recipes.filter(R.compose(keepIds, R.prop("uniqueId")));

console.log(JSON.stringify(res));
// => [{"uniqueId":5},{"uniqueId":2}]
Ben Briggs
@ben-eb
@Twizzes Untested but could be shortened :)
const includedIn = flip(includes);

const res = filter(propSatisfies(includedIn(ids), 'uniqueId')) (recipes)
Kevin Thompson
@kthompson
im trying to make a method to convert a list into a map by id with rambda, i have the follow following but its not working as expected:
const assignById = converge(call, [
  flip(assoc),
  prop('id')
]);

assignById({id: 'abc', taco: 'time'}, {}) // => {abc: {id: 'abc', taco: 'time'} }
Kevin Thompson
@kthompson
i think this will work for now
const toMap = R.pipe(
  R.groupBy(R.prop('id')),
  R.map(R.head)
)
Brad Compton (he/him)
@Bradcomp
converge sets its arity based on the highest arity of the branch functions
Kevin Thompson
@kthompson
yea i was reading that but still couldnt really figure it out
Brad Compton (he/him)
@Bradcomp
Since assoc has an arity of 3 it will take all 3 arguments before passing the results to call
if you need to partially apply a function in converge you can either do it manually (x) => flip(assoc)(x) or use a helper function like arity
Kevin Thompson
@kthompson
i dont see arity but thanks for the info
Brad Compton (he/him)
@Bradcomp
Sorry, it's called nAry
arity seems like a more reasonable name lol
Kevin Thompson
@kthompson
Yea. That gives me something like
const toMap2 = R.reduce(
  R.flip(
    R.uncurryN(
      2, 
      R.converge(R.call, [
        x => R.flip(R.assoc)(x),
        R.prop('id')
      ])
    )
  ), 
  {}
);
i think the other implementation is a bit more clear/concise though
Twizzes
@Twizzes
@kthompson can you use Object.entries?
Kevin Thompson
@kthompson
i'm taking an array of objects and turning it into a map with the object's id as the key.
const toMap = R.pipe(
  R.groupBy(R.prop('id')),
  R.map(R.head)
)
is the simplest way i can come up with
Brad Compton (he/him)
@Bradcomp

i think the other implementation is a bit more clear/concise though

:+1: