These are chat archives for ramda/ramda

26th
Jul 2017
Robert Mennell
@skatcat31
Jul 26 2017 00:02
@Redmega you'll also see an increase in performance with other optimizations
wait I just noticed something about your last function... need ot fix the test
@Redmega hasPaths doesn't work?
Robert Mennell
@skatcat31
Jul 26 2017 00:17
@Redmega I'm not certain hasIgnoredPairs works either
you may want ot check that the functions are working in the first place?
Angel J Piscola
@Redmega
Jul 26 2017 00:44
Oh shoot
Thought they were working... Let me see
I think I messed them up in the copy-paste to the big REPL
In any case thanks for the help, we'll go with the more readable one since the performance between them is negligible
Isaac
@IsaacRaja_twitter
Jul 26 2017 07:29
can I ask for refactoriing tips here?
James
@aretecode
Jul 26 2017 07:38
@IsaacRaja_twitter go for it
Radu Dascalu
@NulledGravity
Jul 26 2017 08:41
Hello everyone
Isaac
@IsaacRaja_twitter
Jul 26 2017 08:43

        itineraryArr = R.filter(
          (itinerary) => {
            let itr = R.map((itt) => R.prop('uuid', itt), itinerary.themes);
            return allCheckedThemes.length > 0 && R.intersection(allCheckedThemes, itr).length > 0 || false;
          }, origItineraryData);
Adam Szaraniec
@mimol91
Jul 26 2017 08:44
|| false what is it for ?
Isaac
@IsaacRaja_twitter
Jul 26 2017 08:45
it should return false if it doesn't match those conditions
I mean it shouldn't filter it
Adam Szaraniec
@mimol91
Jul 26 2017 08:45
R.intersection(allCheckedThemes, itr).length > 0 it will return bool I think
Isaac
@IsaacRaja_twitter
Jul 26 2017 08:45
how do i refactor with tacit
I mean without passing the data altogether at first
@mimol91 yes
This is a straight translation of the code from lodash. I don't know how to refactor it in ramda way of not passing the data
Adam Szaraniec
@mimol91
Jul 26 2017 09:04
I m not Ramda expert, but I can try, Do You have some example data?
Its not a pure cos you are accessing allCheckedThemesby closure
Gleb Bahmutov
@bahmutov
Jul 26 2017 13:35
Sten-H
@Sten-H
Jul 26 2017 13:41
I asked about something very similar yesterday, guess I'm a slow learner. (id) => R.find(R.propEq('id', id)) I feel like this should be possible to make pointfree by sort of lifting out the propEq from the find or something?
Sten-H
@Sten-H
Jul 26 2017 15:20
Aha I solved it with useWith
Brad Compton (he/him)
@Bradcomp
Jul 26 2017 15:39
const filterer = (allCheckedThemes) => pipe(
  prop('themes'),
  pluck('uuid'),
  compose(Boolean, length, intersection(allCheckedThemes))
);

filter(filterer(allCheckedThemes), origItineraryData)
Something like this should work, can you give some sample data for the origItineraryData data and allCheckedThemes? Then we could test it out
Sorry, meant to tag @IsaacRaja_twitter
Bijoy Thomas
@bijoythomas
Jul 26 2017 16:01
A JS scratch pad for Sublime. Useful if you want to play around with ramda and other libs too. Not as fancy as mancy but nice to just work within Sublime. https://packagecontrol.io/packages/JavaScript%20Scratch%20Pad
Adrian Perez
@blackxored
Jul 26 2017 18:06
Hello guys
anyone around for a quick question?
I'm using ramda with ramda fantasy, and I've seen a pattern that I'm 100% sure there's an easy way to do
disclaimer: new to monads, half-new to ramda
Robert Mennell
@skatcat31
Jul 26 2017 18:07
what's the pattern?
Adrian Perez
@blackxored
Jul 26 2017 18:08
a factory function that uses a reader monad and passed the environment to the inner function

see: `` const inner = (param) => { return Reader.ask.map((env) => { console.log(innerMost param: ${param}, someVar: ${env.someVar}`)
});
};

const factory = Reader(env => ({
innerMost: (param) => inner(param).run(env),
}));

factory.run({ someVar: 'someVar' }).innerMost('param'));
```

oops, github flavored
const inner = (param) => {
  return Reader.ask.map((env) => {
    console.log(`innerMost param: ${param}, someVar: ${env.someVar}`)
  });
};

const factory = Reader(env => ({
  innerMost: (param) => inner(param).run(env),
}));

factory.run({ someVar: 'someVar' }).innerMost('param'));
how would you rewrite factory to you don't have to do this for every single function
I'm also open to any other ways of writing the inner functions
assume that env.someVar would be a dependency I will always need across a set of functions
there's a typo at the last line, should say inner but hopefully you understand what I'm having trouble with at this point
Robert Mennell
@skatcat31
Jul 26 2017 18:12
a programatic way to call and use functions without knowing what the function is?
Adrian Perez
@blackxored
Jul 26 2017 18:12
That's part two of the problem, but I haven't gotten there yet
I need an easier way to get a function that will invoke run for me
with a bound env that you give to the factory
offtopic: I'm so gonna destroy my type checker :joy:
Adrian Perez
@blackxored
Jul 26 2017 18:18
So, i'm almost sure that the inner function is written how it would be recommended to, the factory on the other hand it's a mess :P, I've tried with chain, lift, etc and basically the manual invocation of run inside the factory is the only thing that works
Robert Mennell
@skatcat31
Jul 26 2017 18:22
since this sounds more liek a question of how to use a reader, have you seen brina's video on it? https://vimeo.com/105300347
Adrian Perez
@blackxored
Jul 26 2017 18:24
I've seen something similar, but taking a look now, thanks
Adrian Perez
@blackxored
Jul 26 2017 18:34
So it still doesn't solve my problem of having the factory run run for me
Adrian Perez
@blackxored
Jul 26 2017 18:47
is there a contra chain or contra map? probably not using the right term
but basically instead of running run on this, run run on the supplied function
Robert Mennell
@skatcat31
Jul 26 2017 18:50
that's just a wrapper function isn't it? basically a map you could declare what label you'd want to run on it
Adrian Perez
@blackxored
Jul 26 2017 18:55
in a way it is
a wrapper
but i'm wondering if there's an equivalent of chain or ap that'd do that
with bound parameters
in this case the env that i'm passing to the factory
Robert Mennell
@skatcat31
Jul 26 2017 18:56
isn't that env no bound in the Reader context in your factory?
Adrian Perez
@blackxored
Jul 26 2017 18:57
How do you mean, my factory is a Reader
Robert Mennell
@skatcat31
Jul 26 2017 18:57
const factory = Reader(env => ({
innerMost: (param) => inner(param).run(env),
}));
Sten-H
@Sten-H
Jul 26 2017 18:58
Is it possible to chain useWith and converge to make them apply arguments to the same list of functions?
Adrian Perez
@blackxored
Jul 26 2017 18:58
@skatcat31 I'm sorry, didn't quite understand the question
Robert Mennell
@skatcat31
Jul 26 2017 18:59
factory is a Reader that has been passed the function that when given an environment returns an object with a property innermost that is a function that calls inner with the param to call run with env
Adrian Perez
@blackxored
Jul 26 2017 18:59
We pass the env to factory, that returns an object with a list of functions
those inner functions would use ask to get that env context
Is that ok so far?
Robert Mennell
@skatcat31
Jul 26 2017 19:00
right, because it's a Reader
Adrian Perez
@blackxored
Jul 26 2017 19:00
now, i want to invoke methods on the factory
once it's constructed
directly, not by running run on every single method
blackxored @blackxored goes back to OOP land
Adrian Perez
@blackxored
Jul 26 2017 19:01
hahahhaha jk
so I managed to do that with the snippet, defining a factory function that runs run in the inner function
Robert Mennell
@skatcat31
Jul 26 2017 19:02
so what you're asking is there something like map that would instead call run
Adrian Perez
@blackxored
Jul 26 2017 19:02
something like that
pseudo code
innerMost: contraChain(inner, env)
don't mind the naming
contraChain = (...args, env) => inner(args).run(env)
does that make sense?
obviously that's not even valid js but still pseudocode
Robert Mennell
@skatcat31
Jul 26 2017 19:06
https://github.com/ramda/ramda-fantasy/blob/master/docs/Reader.md from what I can tell it's built into Ramda-fantasy by implimenting it as a monad, which is a functor, so map should work fine, and chain should work fine. You're asking how do you call it on the inner context if the inner context is a Reader
Adrian Perez
@blackxored
Jul 26 2017 19:06
Bingo
Robert Mennell
@skatcat31
Jul 26 2017 19:06
so why not use chain?
or are you hoping ot avoid that, something like Reader.T?
Adrian Perez
@blackxored
Jul 26 2017 19:07
i can't pass the env if I use chain, for some reason gives me an array
Robert Mennell
@skatcat31
Jul 26 2017 19:09
Adrian Perez
@blackxored
Jul 26 2017 19:09
it seems like I want ap
let me check that one
so, that one is on the instance, correct?
Robert Mennell
@skatcat31
Jul 26 2017 19:10
correct
it will chain the reader, so instead of a reader containing a reader, it will be a reader containing a result
Adrian Perez
@blackxored
Jul 26 2017 19:10
so, two problems with that, I don't have access to an instance inside factory, do I? second problem, it says it will return a new reader
Rick Medina
@rickmed
Jul 26 2017 19:10
@blackxored maybe specify your use case? Maybe there's a xy problem here?
Adrian Perez
@blackxored
Jul 26 2017 19:11
i don't want the inner functions to have to be called by invoking run on them
Robert Mennell
@skatcat31
Jul 26 2017 19:12
/**
 * Env        :: { dbConn: DbConnection, httpClientPool: HttpClientPool }
 * selectOne  :: String -> Table -> Object -> DbConnection -> Future Error DbRow
 * fetchImage :: URL -> HttpClientPool -> Future Error Image
 */

//:: String -> Reader Env (Future Error DbRow)
fetchUser = email => Reader(env =>
  selectOne('email = :email', Users, { email: email }, env.dbConn));

//:: String -> Reader Env (Future Error ImageData)
fetchUserImage = email => Reader.ask.chain(env =>
  fetchUser(email).map(futureUserRow => futureUserRow.chain(userRow =>
    fetchImage(userRow.imageURL, env.httpClientPool))));

//:: Future Error ImageData
fooImageFuture = fetchUserImage('foo@example.com').run({
  dbConn: initDb(),
  httpClientPool: initHttpClientPool
});
something like that?
Adrian Perez
@blackxored
Jul 26 2017 19:12
@rickmed I'm taking the hardest road to share a dependency across a set of functions, wrap all those functions into a factory that's given a context once, and then all functions invoked by it have that context automatically
@skatcat31 I saw this example
Robert Mennell
@skatcat31
Jul 26 2017 19:13
right, and it shows that the env is being passed along through map and chain isn't it?
Adrian Perez
@blackxored
Jul 26 2017 19:13
I completely missed the Reader.ask.chain call
Rick Medina
@rickmed
Jul 26 2017 19:14
right, when composing Readers all functions have access to the env at any time
Adrian Perez
@blackxored
Jul 26 2017 19:14
still gets me a reader back
one sec, you might be onto something
Rick Medina
@rickmed
Jul 26 2017 19:15
that is how you work with these ADTs normally, you keep composing them until a final impure call (run)
so for example, you can lift values into Reader and keep composing them, or have natural transformations if you need to compose with things that don't return Reader (Either, Maybe...)
or use monad transformers
Adrian Perez
@blackxored
Jul 26 2017 19:17
Still keeps getting me readers
RIP
Robert Mennell
@skatcat31
Jul 26 2017 19:18
well yeah, it should until your final run call with the env
Adrian Perez
@blackxored
Jul 26 2017 19:19
Hmm
Have this working
const inner = (param) => {
  return Reader.ask.map((env) => {
    console.log(`innerMost param: ${param}, someVar: ${env.someVar}`)
  });
};

const contraChain = (innerFn, env) => (...args) => innerFn(...args).run(env); 
const factory = () => Reader(env => ({
  innerMost: contraChain(inner, env)
}))

factory().run({ someVar: 'someVar' }).innerMost('param');
hopefully makes more sense at what i'm trying to do
this works BTW :joy_cat:
also works without factory being a function
Now that we have a way to do it, what would be the way to do it?
Rick Medina
@rickmed
Jul 26 2017 19:27

@rickmed I'm taking the hardest road to share a dependency across a set of functions, wrap all those functions into a factory that's given a context once, and then all functions invoked by it have that context automatically

Why not just chain/map (and .ask for the functions that need the dependency) and pass the dependency just once at the end on the composition with .run?

Adrian Perez
@blackxored
Jul 26 2017 19:29
Can you give an example?
Rick Medina
@rickmed
Jul 26 2017 19:29
For example, when you say "Still keeps getting me readers", what is the problem?
Adrian Perez
@blackxored
Jul 26 2017 19:29
Ok, here's the final user api
Rick Medina
@rickmed
Jul 26 2017 19:30
the example Robert posted
Adrian Perez
@blackxored
Jul 26 2017 19:30
const instance = factory.run({ someVar: 1});
// At a later time
instance.inner(2)
in the other example, there's no factory, so the entrypoint is fooImageFuture
right?
Rick Medina
@rickmed
Jul 26 2017 19:36
have you seen the last example in Brian's video? maybe that helps
Adrian Perez
@blackxored
Jul 26 2017 19:37
Yes, just saw it earlier, I couldn't find something similar
When you think about it my rusty contraChain does:
  1. Return a function with bound parameters (passed params) to invoke the inner function with
  2. Invoke run on the result of that (given I get a Reader back), with the environment (using closures so not optimal)
that last example has that issue with having to invoke run on it
Rick Medina
@rickmed
Jul 26 2017 19:49
why is that a problem?
when you do factory.run(...) and innerMost(...) is like you're passing two different env but I don't get why
Adrian Perez
@blackxored
Jul 26 2017 19:50
LOL another way innerMost: compose(invoker(1, 'run')(env), inner)
So, i'm not passing two environments
innerMost(...) is params to the function
run(...) is the environment
it's just to simplify the API
apologies for the naming
I'm hoping to simplify the API since i'm in the context of something that gets initialized once, then used across a set of methods that would invoke this functions (or the functions inside the factory) maybe i'm mixing paradigms too much, think
getUser(1).run({ db: '...'})
vs
factory.getUser(1)
( you passed the environment somewhere else while initializing)
here the latter factory would be result of running factoryFn (the one we've been talking about) eg instance = factory.run({ db: '...'})
so instance.getUser(1) instead
to make it clearer
Rick Medina
@rickmed
Jul 26 2017 19:56
ok, I think now I'm kind of getting your use case. So basically you have some OOP code (a factory that initializes something with some methods) and you want those methods to have access to a shared env and you thought of using Reader for that?
Adrian Perez
@blackxored
Jul 26 2017 19:57
I have some functions, all taking a common argument, a dependency right
that dependency gets initialized once
To give even more context
This is an object map of functions
Rick Medina
@rickmed
Jul 26 2017 19:58
ok, so Reader gives you the ability of having access to an env to a function "as if it were right there" but you are passing it at the end with run
Adrian Perez
@blackxored
Jul 26 2017 19:59
every function in that resolver map takes a context
i was hoping to initialize this context once with the dependency and then invoke context.getSomething(withInnerParams)
since that context gets passed around for you
Adrian Perez
@blackxored
Jul 26 2017 20:05
That made even less sense did it? :P
Rick Medina
@rickmed
Jul 26 2017 20:07
no, it made me understand your use case (xy problem :) ), although, I'm not sure if Reader is quite right for that bc what is gives you is a way to compose functions which have a shared env and I'm not sure how those resolver methods are composed with each other
Adrian Perez
@blackxored
Jul 26 2017 20:08
they're not composed
maybe i'm after all going after the wrong subject
since this is only part 1 of my plan
here's what I want overall
let's say resolvers are just functions that call an api
goal #1 is to have them share context (no global variables, don't wanna wrap the thing in a class)
goal #2 is having those functions be pure, describe what should happen
goal #3 is avoiding having to define every single function by hand
Robert Mennell
@skatcat31
Jul 26 2017 20:14
sorry the way that message was worded was more offensive then what I wanted. How are you going to avoid a context(class, module, readers, etc.)?
Adrian Perez
@blackxored
Jul 26 2017 20:16
sorry about the generic naming
probably makes things more confusing
Rick Medina
@rickmed
Jul 26 2017 20:27
@blackxored since those methods aren't composed with each other, have you considered passing a partially applied function with the context?
Adrian Perez
@blackxored
Jul 26 2017 20:28
context here as in framework context, or as in our "factory"
??
Rick Medina
@rickmed
Jul 26 2017 20:28
as whatever the shared env is (no idea of your specific use case)
Adrian Perez
@blackxored
Jul 26 2017 20:29
That's why I used to have
but all the inner functions have the dependency as part of the argument list
which i'm not sure is a good idea but that's part of what I wanted to get rid of
s/why/what
Rick Medina
@rickmed
Jul 26 2017 20:36
do you have a current/concrete piece of code? and see what you want to change (you mentioned you were working with a framework so, eg, I assume you can't change those functions...)
Adrian Perez
@blackxored
Jul 26 2017 20:37
It's too large to many sense of imho
But I think the overall concept is on those goals that I made above
how to avoid passing a common parameter to every single function
how to make every function side-effect free
and finally (and maybe even optionally) how to make a OOP-like api so I don't have to go the python2 way on everything :P
This in the interest of learning, contrainChain seems to work good enough :P
Rick Medina
@rickmed
Jul 26 2017 21:00

how to avoid passing a common parameter to every single function

This is a common question. Techniques I tend to reach to: closures, partially applied functions, rethink data modeling , lastly, something like Reader (at least in js).

Think about operations as composition of function helps
good luck! :)
Robert Mennell
@skatcat31
Jul 26 2017 21:13
Is it weird that Readers seem like anotehr way to compose a "static" class to me?
Adrian Perez
@blackxored
Jul 26 2017 21:14
Yeah I'm using both closures and partially applied functions, it seems to me that readers was supposed to solve that problem tbh :P
Robert Mennell
@skatcat31
Jul 26 2017 21:16
Seirously feel like a reader is creating a closure... Maybe I'm just crazy...
jonathandion
@jonathandion
Jul 26 2017 21:18

Hi, what’s the best way to merge 2 Array’s right to left.

R.concat([{ a: 1},{b : 2}], [{ a : 2}])
expecting : [{a: 2}, {b : 2}]

Thanks.

Brad Compton (he/him)
@Bradcomp
Jul 26 2017 21:32
Do you want objects at the same index to be merged, or objects with the same keys, or what?
Or do you want objects on the right to replace objects on the left at the same index?
jonathandion
@jonathandion
Jul 26 2017 21:37
same keys
Brad Compton (he/him)
@Bradcomp
Jul 26 2017 21:38

So would this return the same thing then?

arrayMerge([{b : 2}, { a: 1}], [{ a : 2}])

What about this?
arrayMerge([{a: 1, b: 1}, {a: 2, b: 2}], [{a: 3}, {b: 4}])
Bijoy Thomas
@bijoythomas
Jul 26 2017 21:41
@Bradcomp is there a function in ramda like arrayMerge?
or you are just suggesting the API?
Brad Compton (he/him)
@Bradcomp
Jul 26 2017 21:42
The closest thing is prolly zipWith
Yeah, just trying to nail down the expected behavior, shouldn't have used R.
Bijoy Thomas
@bijoythomas
Jul 26 2017 21:42
ah .. gotcha
Brad Compton (he/him)
@Bradcomp
Jul 26 2017 21:43
There :smile:
Bijoy Thomas
@bijoythomas
Jul 26 2017 21:46
@jonathandion R.compose( R.reduce(merge, {}), R.concat )([{ a: 1},{b : 2}], [{ a : 2}])
Brad Compton (he/him)
@Bradcomp
Jul 26 2017 21:55
R.reduce(merge, {}) === R.mergeAll
But that will give a single object, not an array
Bijoy Thomas
@bijoythomas
Jul 26 2017 21:58
:thumbsup: thanks for pointing mergeAll out
Brad Compton (he/him)
@Bradcomp
Jul 26 2017 22:00
@jonathandion it might help to know what you're trying to accomplish beyond just a toy example...
Robert Mennell
@skatcat31
Jul 26 2017 22:07
Farthest I got was calling it rlStein( [ left[], right[] ] ) XD
Bravi
@Bravilogy
Jul 26 2017 23:00
is it a good idea to use IO monad within Future's resolve callback?
i.e.
application.fork(console.error, runSomeIO);