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 22:17
    CrossEye commented #2779
  • Jan 31 21:04
    ArturAralin commented #2779
  • Jan 31 20:08
    CrossEye commented #2779
  • Jan 31 18:56
    buzzdecafe commented #2631
  • Jan 31 18:09
    ArturAralin commented #2779
  • Jan 31 16:18
    CrossEye commented #2779
  • Jan 31 16:10
    CrossEye commented #2631
  • Jan 31 16:06
    CrossEye commented #2777
  • Jan 31 14:44
    ArturAralin opened #2779
  • Jan 31 07:39
    inferusvv commented #2631
  • Jan 31 03:07
    sespinozj commented #2771
  • Jan 31 02:33
    machad0 commented #2771
  • Jan 31 02:26
    JeffreyChan commented #2777
  • Jan 30 14:30
    CrossEye closed #2777
  • Jan 30 12:13
    vanyadymousky updated the wiki
  • Jan 30 01:42
    JeffreyChan commented #2777
  • Jan 29 21:06
    vanyadymousky updated the wiki
  • Jan 29 16:28
    CrossEye commented #2777
  • Jan 29 15:50
    mbostock commented #2772
  • Jan 29 15:48
    CrossEye commented #2772
pentatronix
@pentatronix
How would one traverse with a lensPath? I have been trying to wrap my brain around partial.lenses for a while and I get nowhere :(
What I would be after is the equivalent to x = lensPath(['a', *, 'd']); which would return all d children of any elements that are children of a.
Twizzes
@Twizzes
const obj = { a: [{ d: 1 }, { d: 2 }, { d: 3 }] };
const aChildrenD = R.pipe(R.view(R.lensProp("a")), R.map(R.view(R.lensProp("d"))));

console.log(aChildrenD(obj));
// => [1,2,3]
this only works if a can be operated on by R.map
@pentatronix
pentatronix
@pentatronix
@Twizzes , ah makes sense. So effectively you build up lenses of the sub objects, and wherever you need to you just compose with map or reduce etc.
pentatronix
@pentatronix
Thanks. I had not seen a particularly clear usage for lenses, especially in complex read only situations.
Alex McKay
@alexandermckay
I am trying to a find a function in the ramda library that does the same thing as the callback helper function I have written below. Could someone please let me know if it exists?
const callback = (fn) => (...args) => () => fn(...args)

const obj = {
  method: (x, y) => x + y
}

const exists = always(has('method', obj))
const execute = callback(prop('method', obj))('Invoke ', 'Fn')

when(exists, execute)(null)
Brad Compton (he/him)
@Bradcomp
@alexandermckay That might be what you are looking for.
However, your version looks fine too
Alex McKay
@alexandermckay
You're a legend, thank you
Ben Briggs
@ben-eb
Hi friends. I've got some push back from our team about functional stuff and wondered if you had any advice. Specifically some of our team are struggling with currying, I think this may have been exacerbated because we are using a lot of closures to do dependency injection. Do you have any advice on how I could teach this stuff or any debugging patterns that may have helped you out? I do understand some of that pain and wonder if it might be reasonable to try out typescript, though I have seen posts here about typing pains with ramda in the past. To be honest I really like the flexibility of dynamic types but static typing does have good developer ergonomics (especially for a developer trying to extend some unfamiliar code)
I think sometimes I might struggle with the why of FP nowadays because it's kind of instinctive to me. And I'm conscious that I need to surface those things too because I'm essentially leading the charge of FP at our work
Ben Briggs
@ben-eb
I am also worried that in order to get the benefits of FP we might need to go further down the rabbit hole (e.g. algebraic types and especially Futures - so that we can end up with more loosely coupled units) and I might alienate people. I guess I need to find balance :slight_smile:
Brad Compton (he/him)
@Bradcomp

I would push for ADTs over currying for sure. Point free without static types can make things harder to read until used to it. It's really nice if your team is into it, but otherwise I think it's best used sparingly. There are certain places where currying makes a ton of sense (DI is often one of those cases).

I can't tell you how often I see a good use for Maybe or Either. They come up everywhere, and are especially helpful in dynamically typed code.

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)