These are chat archives for ramda/ramda

9th
May 2016
Lewis
@6ewis
May 09 2016 13:07
Maybe
@Bradcomp what's maybe
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:04
@6ewis It's a way to explicitly model optional values in your data type.
Let's look at head for instance:
R.head
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:05
Note the return type is a | undefined, which means we need to do a nil check to handle the result
@ram-bot compose(add(1), head)([1,2,3])
ram-bot
@ram-bot
May 09 2016 15:05
2
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:06
@ram-bot compose(add(1), head)([])
ram-bot
@ram-bot
May 09 2016 15:06
NaN
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:07
So a Maybe can model that without having to do nil checks
@ram-bot S.head([1,2,3])
ram-bot
@ram-bot
May 09 2016 15:07
Just(1)
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:07
@ram-bot S.head([])
ram-bot
@ram-bot
May 09 2016 15:07
Nothing()
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:08
Because your value is wrapped in a Maybe, you can't just access it directly, which prevents you from accidentally using an undefined valus
@ram-bot compose(add(1), S.head)([])
ram-bot
@ram-bot
May 09 2016 15:09
NaN
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:09
'Scuse me
@ram-bot compose(map(add(1)), S.head)([])
ram-bot
@ram-bot
May 09 2016 15:09
Nothing()
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:09
Once you have your value in a container, you need to call map to access it.
Or some other functions
It allows you to build up these data pipes without having to pepper your code with nil checks.
Once you need the value, you can use something like maybe (lowercase) to get it out.
@ram-bot compose(S.maybe('failed', toString), map(add(1)), S.head)([1, 2, 3])
ram-bot
@ram-bot
May 09 2016 15:13
'2'
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:14
@ram-bot compose(S.maybe('failed', toString), map(add(1)), S.head)([])
ram-bot
@ram-bot
May 09 2016 15:14
'failed'
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:14
This blog post has a more in depth explanation of some of the concepts: http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
The S stands for Sanctuary by the way.
Lewis
@6ewis
May 09 2016 15:30
@ram-bot R.head([])
@ram-bot S.head([])
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:32
@ram-bot
[R.head([]), S.head([])]
ram-bot
@ram-bot
May 09 2016 15:32
[ undefined, Nothing() ]
Lewis
@6ewis
May 09 2016 15:33
@Bradcomp If I understand you correctly, S aka Sanctuary wrap the value into a Maybe
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:34
Correct. S provides type safe versions for many of Ramda's functions, head being one of them
Another good example would be prop
Lewis
@6ewis
May 09 2016 15:35
@Bradcomp hold on, I didn't get the map(add)
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:35
@ram-bot R.prop('name')({})
ram-bot
@ram-bot
May 09 2016 15:35
undefined
Lewis
@6ewis
May 09 2016 15:35
compose(S.maybe('failed', toString), map(add(1)), S.head)([1, 2, 3]
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:35
@ram-bot S.get(String, 'name')({})
ram-bot
@ram-bot
May 09 2016 15:35
Nothing()
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:36
@ram-bot S.get(String, 'name')({name: 'Brad'})
ram-bot
@ram-bot
May 09 2016 15:36
Just("Brad")
Lewis
@6ewis
May 09 2016 15:36
@ram-bot compose(S.maybe('failed', toString),add(1), S.head)([1, 2, 3]
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:36
@ram-bot S.get(String, 'name')({name: 12345})
ram-bot
@ram-bot
May 09 2016 15:36
Nothing()
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:36
@6ewis You gotta put it in back tics
`code goes here`
Lewis
@6ewis
May 09 2016 15:38
@Bradcomp I thnk I get it now.
R.get
ram-bot
@ram-bot
May 09 2016 15:38
Error: No such function get
Lewis
@6ewis
May 09 2016 15:38
S.get
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:39
S.get is a typesafe version of R.prop
but I don't think @ram-bot will tell you about it
Lewis
@6ewis
May 09 2016 15:46
@Bradcomp maybe is basically useful for such situations: let x = (user || {name: 'failed'}).name; in R parlance it would be
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:52
@6ewis It's useful for more than that though. It can make your code safer by forcing you to explicitly consider the null case. I wrote mongo access layer that returns a Maybe from a findOne, so you always have to consider the case that the item doesn't exist in the database. The nice thing is that, if you have a data pipeline, mapping over a Maybe is safe. Nothing always maps to nothing, so you can write your functions as though you know the item will be there.
Lewis
@6ewis
May 09 2016 15:52
compose(S.maybe('failed', R.identity), S.get(String, 'name'))({})
Raine Virta
@raine
May 09 2016 15:54
see S.fromMaybe
Lewis
@6ewis
May 09 2016 15:54
@Bradcomp that's funny because I have a small utility function that i use to check the null value (basic) and i always call it maybe. For once I agree with the name :p
@Bradcomp did I get that last example right
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:55
:+1:
@ram-bot
compose(S.maybe('failed', R.identity), S.get(String, 'name'))({})
ram-bot
@ram-bot
May 09 2016 15:55
'failed'
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:55
Yes!
But you could also go:
@ram-bot
compose(S.fromMaybe('failed'), S.get(String, 'name'))({})
ram-bot
@ram-bot
May 09 2016 15:55
'failed'
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:56
fromMaybe is like maybe but without applying a function
Lewis
@6ewis
May 09 2016 15:56
that's amazing. @Bradcomp . question about S. I never used it in my codebase, should we pull another lib or is it included in R
Brad Compton (he/him)
@Bradcomp
May 09 2016 15:56
It's not included in Ramda
Lewis
@6ewis
May 09 2016 15:57
so it's built on top of R?
Brad Compton (he/him)
@Bradcomp
May 09 2016 16:00
I think for now that's correct, but eventually I think they're planning on removing the dependency. For more backstory see this: https://blog.plaid.com/sanctuary/
Lewis
@6ewis
May 09 2016 16:02
@davidchambers do you still write clojure?
@Bradcomp I'l probably switch to that instead of R
pros/cons?
Brad Compton (he/him)
@Bradcomp
May 09 2016 16:06
See here in the sanctuary gitter: https://blog.plaid.com/sanctuary/
David Chambers
@davidchambers
May 09 2016 16:06
Very nice explanation of the Maybe type, @Bradcomp!
Brad Compton (he/him)
@Bradcomp
May 09 2016 16:07
Oops, copy paste is failing me
Thanks @davidchambers
David Chambers
@davidchambers
May 09 2016 16:08
@6ewis, I've written very little Clojure. Just enough to know that I like it (though I'm very interested in types at the moment, so Clojure doesn't hold the appeal it once did).
Brad Compton (he/him)
@Bradcomp
May 09 2016 16:13

hold on, I didn't get the map(add)

So calling map allows you to reach into the Maybe and manipulate a value. If you have Just(1) you can't go Just(1) + 1, instead you need something that lets you do Just(1 + 1). map does that for you.

@ram-bot map(add(1), S.Maybe.of(1))
ram-bot
@ram-bot
May 09 2016 16:14
Just(2)
Lewis
@6ewis
May 09 2016 16:25
@davidchambers I agree. @Bradcomp explain what one's might deem complex in a very simple fashion with clear examples
David Chambers
@davidchambers
May 09 2016 16:31
Indeed. That's a wonderful skill.
One way to gain an intuition for the Maybe type is to consider how one operates on an array with at most one value.
@ram-bot
R.map(R.inc, [])
ram-bot
@ram-bot
May 09 2016 16:33
[]
David Chambers
@davidchambers
May 09 2016 16:33
@ram-bot
R.map(R.inc, [42])
ram-bot
@ram-bot
May 09 2016 16:33
[ 43 ]
David Chambers
@davidchambers
May 09 2016 16:34
Maybe a is a bit nicer than Array a, though, as it makes it clear that there's at most one a.
Brad Compton (he/him)
@Bradcomp
May 09 2016 16:37
@davidchambers I like that!
Brad Compton (he/him)
@Bradcomp
May 09 2016 18:22
R.props
Emilio Srougo
@Emilios1995
May 09 2016 19:53
Hi everyone, I have a problem, does anyone know a way Ramda can help me?
I have an array like this one:
[
{ id: 1, elements: [{ name: 'lorem'}, { name: 'ipsum' }] },
{ id: 2, elements: [{ name: 'sit' }, { name: 'amet' }] }
]
And I want to end up with this
[
{ id: 1, elements: [{ name: 'lorem', index: 1 }, { name: 'ipsum', index: 2 }] },
{ id: 2, elements: [{ name: 'sit', index: 3}, { name: 'amet', index: 4 }] }
]
Brad Compton (he/him)
@Bradcomp
May 09 2016 19:59
@Emilios1995 Do you want the indexes to be one based or zero based?
Vladimir Starkov
@iamstarkov
May 09 2016 19:59
You might need r.map, r.evolve
Emilio Srougo
@Emilios1995
May 09 2016 19:59
one based
Vladimir Starkov
@iamstarkov
May 09 2016 20:00
And r.addIndex
Brad Compton (he/him)
@Bradcomp
May 09 2016 20:00
OK
See here for one such implementation: http://goo.gl/xTIWqJ
As @iamstarkov said, we're using addIndex
and map and evolve :-D
Though, I see now it doesn't quite do what you asked :-/
Emilio Srougo
@Emilios1995
May 09 2016 20:04
Yea :(
Brad Compton (he/him)
@Bradcomp
May 09 2016 20:06
Here's my cheater way: http://goo.gl/j5fXQU
@Emilios1995 If you wrap it in a function it becomes more pure, and it works! http://goo.gl/GAjnGS
Emilio Srougo
@Emilios1995
May 09 2016 20:12
Sure, it's prefect, and doesn't look cheaty at all.
Thank you :)
Aldwin Vlasblom
@Avaq
May 09 2016 20:13
Here's a way to do it without mutation using reduce; http://goo.gl/8YCpwc
Emilio Srougo
@Emilios1995
May 09 2016 20:17
That looks great, but why do you say without mutation? Brad's solution doesn't mutate the original array, does it?
Brad Compton (he/him)
@Bradcomp
May 09 2016 20:18
@Avaq That's cool! I figured the non-mutating version would need to use reduce, but I just couldn't put it together in a clean way. I like the way you carry the index along with you in the accumulator.
@Emilios1995 You are correct, but I'm relying on my ability to mutate the offset from within my mapping function
Aldwin Vlasblom
@Avaq
May 09 2016 20:20
There's a pattern there. See the reduce, concat, assoc, and the exact same again one level deeper? I think the solution could become very elegant if that's abstracted in a general way.
@Emilios1995 Brad's solution is fine, it's even "more performant". The mutationless solution here is mostly for sports. I find it pays to write complex imperative loops in terms of reduce because it forces you to think about all the edge cases, and reveals the patterns.
Emilio Srougo
@Emilios1995
May 09 2016 20:28
Sure, the way you worked it out is very interesting indeed
Brad Compton (he/him)
@Bradcomp
May 09 2016 20:44
Another downside to my code is that it relies on an implementation detail of map, namely that it goes through the elements of your list in order. With reduce the order is explicit.
In other words, if map were implemented in parallel, my code would break
Aldwin Vlasblom
@Avaq
May 09 2016 20:48
I think if we generalize the pattern here, or rather, specialize reduce to some kind of statefulMap, we'd end up with something that looks a lot like Most.loop.