These are chat archives for ramda/ramda

22nd
Aug 2016
Rafe
@rjmk
Aug 22 2016 09:37
@xgrommx ((:) .) ~ S.B(R.prepend)?
@JAForbes Your explanations of chain vs map are, as always, great! I might not use the examples that take / return bare values, as they're not really to spec (assuming the spec is supposed to be Haskell-like / fantasy-land-ish). In map, it's a bit weird to see the bare values and in chain the function should really be of the form Monad m => (a -> m b), which multiply(2) isn't.
Would be interested to hear if you agree / disagree?
Denis Stoyanov
@xgrommx
Aug 22 2016 10:19
@rjmk I need to write it in Ramda map = flip foldr ([]) . ((:) .)
Rafe
@rjmk
Aug 22 2016 10:33
Ah, I believe you'll need Sanctuary's reduce as well as Sanctuary's compose. One moment!
Scott Christopher
@scott-christopher
Aug 22 2016 10:40
@xgrommx The pointful version of that would be:
@ram-bot
const map_ = (fn, xs) =>
  reduceRight((xs_, x) => prepend(fn(x), xs_), [], xs)

map_(inc, [1, 2, 3])
ram-bot
@ram-bot
Aug 22 2016 10:40
[ 2, 3, 4 ]
Denis Stoyanov
@xgrommx
Aug 22 2016 10:41
@scott-christopher I know about pointful, but I need point-free
Rafe
@rjmk
Aug 22 2016 10:42
@xgrommx It's going to be very ugly, because in both Ramda and sanctuary the reducing function has to be a -> b -> a rather than b -> a -> a
Denis Stoyanov
@xgrommx
Aug 22 2016 10:45
@rjmk we can use flip
@rjmk const reduceRight_ = curry((fn, init, source) => source.reduceRight(flip(fn), init))
Rafe
@rjmk
Aug 22 2016 10:57
@xgrommx No we can't because flip in Ramda isn't designed for truly curried functions

But if we define

const flop = f => x => y => f(y)(x)

const reduce_ = fn => init -> source => S.reduce(flop(fn), init, source)

const map_ = S.B(flop(reduce_)([]), S.B(append))

James Forbes
@JAForbes
Aug 22 2016 11:00

@rjmk yeah I agree with everything you said, the identity thing with map was surprising to me. I was expecting that to throw or return undefined. It is kind of interesting though, maybe raw values are just treated as identities? Maybe the implementation is that way for a reason. And if so, it makes that usage of chain, a little less strange.

multiply(2) is a poor usage example of chain though, but I really just wanted to illustrate the return type behaviour. The input was an array but the output was a value. Where as with map the input was an array and the output is an array. I think grasping that is the most important aspect when comparing to promises, even if it isn't an accurate depiction of chain.

I find it hard to succinctly explain things while still being 100% accurate. Its something I'm working on.

Rafe
@rjmk
Aug 22 2016 11:00
Anyway, probably better just to do pointfully
Rafe
@rjmk
Aug 22 2016 11:09

@JAForbes

I find it hard to succinctly explain things while still being 100% accurate. Its something I'm working on.

You're doing a great job!

I really just wanted to illustrate the return type behaviour

Yeah, I get that. I think I'm still slightly in favour of sticking to functions of the right type. x => [x] has the advantage of possibly leading in to a discussion of laws, x => [x, x] has the advantage of it being slightly clearer what's going on. I do get your point though

Ronn
@ronnross
Aug 22 2016 11:18

Hi all, I was trying to use intersect to create a new list where things over elements matched. something like this

const list1 = [
  { tag: 'ident1', text: 'some text' },
  { tag: 'indent2', text: 'some text' },
  { tag: 'indent3', text: 'more text' }]

const list2 = ['ident1']

R.intersection(list1, list2)

The problem is with list1. I want to match on the tag property, but if I do something like R.prop('tag', list1) it throws an error: Cannot read property 'length' of undefined

I'm not really sure how to do what I want, can anyone help?
Ryan Zeigler
@rzeigler
Aug 22 2016 11:29
i think you want R.intersection(R.map(R.prop('tag'), list1), list2) @ronnross
Ronn
@ronnross
Aug 22 2016 11:31
@rzeigler awesome! That worked. Thanks!
James Forbes
@JAForbes
Aug 22 2016 12:23
@rjmk thanks :D
Konstantin Koniev
@skfd
Aug 22 2016 12:39
Hi! Is there docs on how to read these signatures? ((a … → b) … → [a] → *) → (a …, Int, [a] → b) … → [a] → *)
Ryan Zeigler
@rzeigler
Aug 22 2016 12:58
that type signature is just hard to read
which function is that?
Syaiful Bahri
@syaiful6
Aug 22 2016 12:59
@skfd i am not sure what .. it's mean, but my guess is it take a function that accept a function that accept type a, and an array of a (I guess it map). and it will give you a function that accept a function that accept 2 arguments a and Int (Number), and an array of a (look like the result is the original array map that accept a function that receive 2 arguments - the item and the index). but i am not sure.. :)
Konstantin Koniev
@skfd
Aug 22 2016 13:03
I understood what it does form the example but would like to be able to read this singature notation too :)
like what does all these things mean ..., *, [ ],( ) … →
Thought it might be somewhere in docs
Ryan Zeigler
@rzeigler
Aug 22 2016 13:07
[a ] indicates an array of a
(stuff) is a grouping via precendence for clarity
Ryan Zeigler
@rzeigler
Aug 22 2016 13:08
or just read that :-)
Syaiful Bahri
@syaiful6
Aug 22 2016 13:09
it's called Hindley-Milner type signature.
for .. i dont know what it's mean, it the first time i read it..haha
James Grayling
@jamesgrayling
Aug 22 2016 13:10
(a -> b) is a function from a to b
(a -> b -> c) is a function that takes a and b and returns c. Or takes a and returns a function that takes b and returns c.
Rafe
@rjmk
Aug 22 2016 13:16
The weird ...is to indicate the function is variadic; i.e. takes an unspecified number of arguments.
Konstantin Koniev
@skfd
Aug 22 2016 13:19
Thanks for wiki link! Will study that
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:42
Is there a function for returning what any matches?
Denis Stoyanov
@xgrommx
Aug 22 2016 13:42
@aaronmcadam what do u mean?
James Grayling
@jamesgrayling
Aug 22 2016 13:42
find?
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:42
I'm trying to find a segment in a URL from a list of possible segments
I don't want to forEach over the list
I'll put it on the REPL :)
James Grayling
@jamesgrayling
Aug 22 2016 13:43
the function is find
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:46
Here's the function: http://goo.gl/drZAac
Denis Stoyanov
@xgrommx
Aug 22 2016 13:47
@aaronmcadam reduce + any?
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:47
I can't figure out how to call find with a list though
James Grayling
@jamesgrayling
Aug 22 2016 13:47
find operates on a list.
That's all it does
Denis Stoyanov
@xgrommx
Aug 22 2016 13:47
@aaronmcadam find(predicate, list)?
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:48
I mean how to base its predicate on a list
James Grayling
@jamesgrayling
Aug 22 2016 13:49
use the same predicate you would pass to any
they both operate on lists
Denis Stoyanov
@xgrommx
Aug 22 2016 13:49
@aaronmcadam find(v => v in list, source)?
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:50
It always matches the first element when I do that
James Grayling
@jamesgrayling
Aug 22 2016 13:50
What do ou want it to do?
Get all of them?
Use filter
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:50
I need it to tell me which entity the url matches
James Grayling
@jamesgrayling
Aug 22 2016 13:50
findIndex
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:50
the taskEntities list of entities will only appear once in the URL
They're like sub resources within a heirarchy
But I need the string value itself so I can use it in the breadcrumb label
James Grayling
@jamesgrayling
Aug 22 2016 13:52
You want to find a string in a list and return the string?
James Forbes
@JAForbes
Aug 22 2016 13:52
find ?
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:52
yeah
James Grayling
@jamesgrayling
Aug 22 2016 13:52
That's find
James Forbes
@JAForbes
Aug 22 2016 13:52

It always matches the first element when I do that

It matches the first matching element, isn't that what you want though? @aaronmcadam

Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:52
yes, but I need to base that predicate on the other list
I want to find something within a string (URL), based on another list
of possible values
James Forbes
@JAForbes
Aug 22 2016 13:53
ahh
one sec I'll read your src
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:53
so I'm trying to build the predicate, but I'm missing something
Sorry this is confusing :/
Syaiful Bahri
@syaiful6
Aug 22 2016 13:54
you need to zip them maybe? so both will available on your predicate
James Grayling
@jamesgrayling
Aug 22 2016 13:54
If you applied your function to something in the REPL, it would be a lot easier to see what it's doing and refactor it
James Forbes
@JAForbes
Aug 22 2016 13:55
@aaronmcadam can you add sample data to the repl and apply the fn?
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 13:55
Sure, thanks :)
James Forbes
@JAForbes
Aug 22 2016 13:55
I'm leaning towards an indexBy/groupBy
but can't tell without some data
:D
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:01
Sorry I had to undo my hackings :)
Can you follow what I'm trying to do now?
So for some entities, I just need its title, for the sub-entities, I need to label them (Those have a key of taskId)
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:09
Does that help @JAForbes?
James Forbes
@JAForbes
Aug 22 2016 14:24
@aaronmcadam as a starting point, does this look right?
const urlPath = ' projects/169/tasks/663/attributes';

var f = R.pipe(
  R.split('/')
  ,R.takeLastWhile( R.complement(R.equals)('tasks') )
  ,R.prop(1)
  ,R.concat('Task title: ')
)

f(urlPath) //=> "Task title: attributes"
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:26
That's certainly interesting, yeah!
James Forbes
@JAForbes
Aug 22 2016 14:27
So from there, you could customize the message with converge
or any other thing that is variable
the key check I think could be handled in a separate function
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:27

So, let me just check that I understand this:

Splitting the string, then returning each element until it doesn't equal to tasks

James Forbes
@JAForbes
Aug 22 2016 14:28
@aaronmcadam return each element while they don't equal 'tasks'
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:28
Yeah, I would move this to a different function
Which would leave us with an array of [663, 'attributes'], so we get the second one at position 1
James Forbes
@JAForbes
Aug 22 2016 14:29
For legibility, it might be nice to zip the url with some keys, and they grab the particular property, but its up to you
1 will suffice, but it does seem like a magic number
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:29
it does, could you elaborate a bit more about the zip? (I know what the function does)
James Forbes
@JAForbes
Aug 22 2016 14:30
Yeah sure
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:30
zip(['taskId', 'taskSubresourceSegment']), something like that?
James Forbes
@JAForbes
Aug 22 2016 14:30
const urlPath = ' projects/169/tasks/663/attributes';

var f = R.pipe(
  R.split('/')
  ,R.takeLastWhile( R.complement(R.equals)('tasks') )
  ,R.zipObj(['id', 'title'])
  ,R.prop('title')
  ,R.concat('Task title: ')
)

f(urlPath)
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:31
That's really helpful, thanks!!
I think the takeLast makes a lot of sense for what I'm trying to do
James Forbes
@JAForbes
Aug 22 2016 14:31
@aaronmcadam yeah exactly, just using zipObj so its kind of self documenting (at the expense of cpu cycles :P)
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:32
ya, it does just get thrown away, but it's worth it here, I think
James Forbes
@JAForbes
Aug 22 2016 14:32
yeah its a great helpful util
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:32
I was just starting to write a crappy forEach :D
James Forbes
@JAForbes
Aug 22 2016 14:32
yeah I agree, but I mean, it all depends, you could possible do something like an enum, and then use R.prop(url.title) where url.title == 1 but I mean, why bother :D
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:33
yeah, I understand what you mean
James Forbes
@JAForbes
Aug 22 2016 14:33
yeah whenever I reach for forEach a part of me dies inside
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:33
But then you may as well have an object instead of another object pointing to primitive data like array indices
James Forbes
@JAForbes
Aug 22 2016 14:34
true
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:34
But it's still a good idea I might use in the future, if it's too awkward to zip
Syaiful Bahri
@syaiful6
Aug 22 2016 14:34
you may need to split your functions..
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:34
Yeah I will do @syaiful6 :)
Syaiful Bahri
@syaiful6
Aug 22 2016 14:34
const taskEntities = ['images', 'attributes', 'responses'];

const getTitle = R.path(['title']);
const getParticipantName = R.path(['participantName']);
const getLabel = R.either(getTitle, getParticipantName)

const getSub = R.compose(R.head, R.intersection(taskEntities), R.split('/'))

const key = 'taskId';
const urlPath = '/projects/1/tasks/2/responses/3';
const payload = {
  title: 'Task title'
};

getLabel(payload) // Task title
getSub(urlPath) // responses
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:35
I've already got some cohesion around the label value formatting itself
Syaiful Bahri
@syaiful6
Aug 22 2016 14:35
then you can use either again with that little functions based your taskId
James Forbes
@JAForbes
Aug 22 2016 14:35
@syaiful6 I like your intersection usage :thumbsup:
oh was that in the original?
Syaiful Bahri
@syaiful6
Aug 22 2016 14:36
yes, but most Python dev knew that..haha
James Forbes
@JAForbes
Aug 22 2016 14:36
many ways to skin a function
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:36
oooh
Good spot!
aww but I do like the takeLatest too :D
But intersection expresses the algorithm really nicely too
Syaiful Bahri
@syaiful6
Aug 22 2016 14:37
yes, it's good.. :)
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:38
There's still a lot of Ramda I need to learn :sweat_smile:
James Forbes
@JAForbes
Aug 22 2016 14:38
I barely know most of the functions there for what it's worth, I usually wonder if something exists, and then it does
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:39
Thanks a lot @syaiful6, @JAForbes! I've learned a ton again :)
James Forbes
@JAForbes
Aug 22 2016 14:39
Like, "I've got this great idea for a functio... oh :("
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:39
tehee!
James Forbes
@JAForbes
Aug 22 2016 14:39
my pleasure
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:39
Or you're looking for flatMap and go ohhh chain, chain is a better name :D
Do you think there's anything missing @JAForbes ?
Or stuff you'd like to add?
(from/to Ramda)
James Forbes
@JAForbes
Aug 22 2016 14:41
I wouldn't mind a flipped prop for grabbing stuff from an index with a given key
I do that a lot
I usually call it from
I kind of think operator function order should be flipped, particularly the ones that can act as a predicate, but I am on the fence about it
I'd like a development curry that throws exceptions earlier
And generates the source and evals it, that'd be great for debugging
But all very specific to me, so no not really
I really, really like ramda's api
Denis Stoyanov
@xgrommx
Aug 22 2016 14:44
@aaronmcadam better name is >>= :smile:
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:45
Do you mean this sort of use case @JAForbes : R.flip(R.contains(segments))
I mean, the docs for any show using flip for the predicates
James Forbes
@JAForbes
Aug 22 2016 14:45
@aaronmcadam I generate indexes a lot, like groupBy or indexBy. I like to compute relationships once, and then avoid looping again
common case, you fetch stuff from a server, you var users = indexBy(R.prop('id'), response)
Then you can grab user 'aedasfasddasf' by just going users[id]
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:46
yeah, sounds good!
James Forbes
@JAForbes
Aug 22 2016 14:47
But then you might have a list of ids, and you want to turn them back into users
ids.map(from(users))
instead of ids.map( R.prop(R.__, users) )
but I don't know how useful it would be to others, and flipping prop is pretty easy :D
Syaiful Bahri
@syaiful6
Aug 22 2016 14:48
what's is R.__
James Forbes
@JAForbes
Aug 22 2016 14:48
I kind of want placeholders to go away, but a lot of people like them and they aren't hurting me
@syaiful6 it lets you partially apply a function and skip a argument
Syaiful Bahri
@syaiful6
Aug 22 2016 14:48
oh it's placeholder..
James Forbes
@JAForbes
Aug 22 2016 14:48
yeah
I think it'd be nice if Ramda really embraced safe functions as well. I used to think it was crazy to return a maybe from R.head, but not anymore. But we have Sanctuary, so I guess that is covered.
When I say crazy I mean, reserved for the fp enthusiasts
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:50
haha yea
I found out the other day that R.path is safer than R.prop
James Forbes
@JAForbes
Aug 22 2016 14:51
But I use maybe's everywhere now with devs who don't know or care about functional programming, and when they ask me what it is I just say "oh some Java thing" or "a synchronous promise"
propOr is great too!
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:51
Yeah, but my defaults are nearly always undefined
James Forbes
@JAForbes
Aug 22 2016 14:51
oh interesting
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:51
Async redux state ftw :/
I want to start using containers for my async state
James Forbes
@JAForbes
Aug 22 2016 14:52
common case for me is propOr([], 'list') when doing api calls
Aaron Mc Adam
@aaronmcadam
Aug 22 2016 14:52
yeah, I would use that
Aadi Deshpande
@cilquirm
Aug 22 2016 19:16
Hi, how would i compose 2 checks with an or? something like
R.when(R.or(R.isNil(R.__),R.isEmpty(R.__)),R.always(100))
Brad Compton (he/him)
@Bradcomp
Aug 22 2016 19:16
@cilquirm You should be able to use
R.either
Brad Compton (he/him)
@Bradcomp
Aug 22 2016 19:17
This message was deleted
@ram-bot
R.when(R.either(R.isNil, R.isEmpty), R.always(100))([])
ram-bot
@ram-bot
Aug 22 2016 19:17
100
Aadi Deshpande
@cilquirm
Aug 22 2016 20:41
many thanks @Bradcomp