These are chat archives for ramda/ramda

31st
Jan 2017
James Forbes
@JAForbes
Jan 31 2017 04:42

@rickmed most is great, but I've found flyd's api surface is all I ever need, and I appreciate that every stream is what Rx/most would call a "subject". There's this idea in Rx circles that using subjects directly is "the wrong way". I disagree - I think this stems from an idea that if we let people use subjects they'll use streams incorrectly and instead of defining dependent streams in terms of map or scan, they'll manually update values.

That's a fine argument ^ for a super mainstream cross language, cross stack library like say Rx. But there's a side effect, you end up needing hundreds of operators that have a lot of overlap.

I'm not going to use subjects that way, so why pay the verbosity cost of hundreds of operators. All in all, I think flyd composes more easily, and the resulting code is easier to read/write/modify than e.g. Rx.

I see most as a monadic alternative to Rx, its super fast, its got a great community, I really can't fault it. But flyd is so small, its such a simple api and its so versatile.

I also use mithril a lot, its like a light weight alternative to react, except it has a router and a few other things. Its great. Its about to release 1.0, but in the current version 0.2x there's this helpful data structure called m.prop. Its like a data store for a single property. You can pass it around without running into reference issues. It solves a lot of problems without much fuss. It turns out m.prop and flyd.stream have almost the same getter/setter api, so moving from m.prop to flyd to essentially have reactive stores made a lot of sense in that context.

^ This whole way of thinking, where we design api's that are worse so that beginners don't get confused is a big problem I think. There should be some languages and libraries that follow that principle, but there should also be alternatives. A few examples that come to mind, people think hyperscript is dangerous because there is too many ways a designer ^^ could do the wrong thing. But the other side of the argument is, template languages are quite awkward to use exactly because their avoiding turing completeness, and often that indirection is more likely to cause issues than if they had hyperscript in the first place. Sometimes a sharper knife is safer.

^^ Designers are super smart and can handle a lot more than they're given credit for. By the same token, if your using streams, your probably smart too and can make decisions about when to use or not to use subjects.

So I would never say, don't use most, I would say, flyd is incredible and worth trying out first. Thankfully they both support fantasy land, so if you stick to applicative functors you'll be able to reuse a lot of code if you're migrating to most from flyd at a later point.

Rick Medina
@rickmed
Jan 31 2017 05:33
@JAForbes amazing answer. Yeah rx is too big for my taste - although it was what got me into fp. I was going to go with most but will definitely try flyd first!
James Forbes
@JAForbes
Jan 31 2017 06:00
:) let me know how it goes
Bravi
@Bravilogy
Jan 31 2017 11:02
hi guys. I'm trying to compose two lenses together, but can't seem to be able to do so
const phoneLens = lensProp('phone')
const addressLens = lensPath(['address', 'street'])
const phoneAndAddressLenses = compose(phoneLens, addressLens)
I want to run over function on these two lenses together
is it not possible to do that?
Brian McKenna
@puffnfresh
Jan 31 2017 11:03
over function?
Bravi
@Bravilogy
Jan 31 2017 11:04
R.over
Brian McKenna
@puffnfresh
Jan 31 2017 11:04
looks like modify
should be possible then, what's the problem?
sorry, I'm very familiar with lenses but not so much with Ramda
Aldwin Vlasblom
@Avaq
Jan 31 2017 11:05
I think he wants to run a single operation over two different fields represented by two different lenses.
Bravi
@Bravilogy
Jan 31 2017 11:05
yeah
that's what I'm trying to do @Avaq
Brian McKenna
@puffnfresh
Jan 31 2017 11:05
oh, yeah, optics can't do that
Aldwin Vlasblom
@Avaq
Jan 31 2017 11:06
@Bravilogy When you compose lenses together, you create a new Lens that goes "deeper" into the structure, so compose(phoneLens, addressLens) represents data.address.street.phone.
Bravi
@Bravilogy
Jan 31 2017 11:06
ah I see
what I was thinking was - since lenses essentially create new objects, that new one would get passed to the other lense
yeah I don't know why I thought that
Brian McKenna
@puffnfresh
Jan 31 2017 11:08
that sounds accurate, just in a different way
Bravi
@Bravilogy
Jan 31 2017 11:08
so the solution would be to run over over those 2 lenses separately right?
Brian McKenna
@puffnfresh
Jan 31 2017 11:09
yeah
Bravi
@Bravilogy
Jan 31 2017 11:09
thanks!
yaayy :D that worked
Galileo Sanchez
@galileopy
Jan 31 2017 11:13

I'm trying to make this bit point free, mostly for academic purpose

const  tryCatch = (fn) => R.tryCatch(R.compose(R.T, R.nAry(0, fn)), R.F)()
const  tryCatch2 = R.useWith(R.tryCatch(R.__, R.F), [R.compose(R.T, R.nAry(0)) ]);

however ramda complains about arity, I think it has to do with the fact that tryCatch modifies the arity of the returning function according to the tryier function. I already have an implemented version so, this is purely brain candy. Any suggestions?

Aldwin Vlasblom
@Avaq
Jan 31 2017 11:14

lenses essentially create new objects -- @Bravilogy

Not quite, to my understanding lenses create new lenses, so when you compose them they will kind-of wrap each other. It's the over function that actually knows how to use the lens to create new Objects. So what you're looking for is: compose(over(phoneLens, f), over(addressLens, f)).

Bravi
@Bravilogy
Jan 31 2017 11:15
@Avaq right. yeah, that's what I ended up with:
const phone = lensProp('phone')
const address = lensPath(['address', 'street'])

const hide = lens => over(lens, replace(/\w+/g, '****'))

const updateDetails = compose(hide(phone), hide(address))

const fetchUsers = () =>
    new Task((reject, resolve) =>
        axios.get('http://jsonplaceholder.typicode.com/users')
        .then(resolve).catch(reject))

const fetchUser = id =>
    new Task((reject, resolve) =>
        axios.get(`http://jsonplaceholder.typicode.com/users/${id}`)
            .then(resolve).catch(reject))

const fetchUserAddress = id => fetchUser(id)
    .map(response => response.data)
    .map(updateDetails)

fetchUserAddress(1).fork(console.error, console.log)
Vesa Karvonen
@polytypic
Jan 31 2017 12:03
@Bravilogy partial.lenses supports such simultaneous operations on multiple focuses in several ways. For example, you can define a traversal that modifies both lensed properties:
L.modify([L.pick({phone: "phone", address: ["address", "street"]}),
          L.values],
         R.trim,
         {phone: " 1-23-45678 ",
          address: {street: " Far far away "}})
Bravi
@Bravilogy
Jan 31 2017 12:06
@polytypic awesome, looking into it now
thank you