These are chat archives for ramda/ramda

17th
Mar 2017
Denis Stoyanov
@xgrommx
Mar 17 2017 00:20
@piet-v
const secretMap2 = compose(
  ([pirates, gold]) => ('count of pirates: ' + pirates.length + ' and the count of gold piles: ' + gold.length), 
  props(['pirate', 'pile_of_gold']), 
  groupBy(identity))
Piet Vandeput
@piet-v
Mar 17 2017 00:23
@xgrommx my bad, should've mentioned that key can be missing from the array
that code will fail on undefined.length hence my R.map(R.defaultTo(0))
Josep M Sobrepere
@josepot
Mar 17 2017 00:26
@piet-v why are you doing the R.flatten though?
in the input that you provided the array is flattened already.
Piet Vandeput
@piet-v
Mar 17 2017 00:27
pasted the wrong input, it can be nested one level
Josep M Sobrepere
@josepot
Mar 17 2017 00:27
ok, that makes sense
Piet Vandeput
@piet-v
Mar 17 2017 00:28
fastest I could make it till now, though the usage of default values seems hacky at best lol
const secretMap = R.pipe(
  R.flatten,
  R.groupBy(R.identity),
  ({pirate = [], pile_of_gold = []}) => ('count of pirates: ' + pirate.length + ' and the count of gold piles: ' + pile_of_gold.length)
);
Josep M Sobrepere
@josepot
Mar 17 2017 00:28
I don't know, there are a thousand ways to crack an egg, I don't see anything wrong with your implementation. Although, maybe I would have done a straightforward reduce...
maybe it's a lot more imperative... I don't know:
R.reduce(
  (result, entry) => (
    entry === 'pirate'       ? R.evolve({ pirates: R.inc }) :
    entry === 'pile_of_gold' ? R.evolve({ gold: R.inc }) :
                               R.identity
  )(result),
  { pirates: 0, gold: 0 }
)
Piet Vandeput
@piet-v
Mar 17 2017 00:29
sec, I've done that as well but more ugly lol
const reducer = (acc, value) => R.evolve({[value]: R.inc})(acc);
const accumulator = {pirate: 0, pile_of_gold: 0};
const secretMap = R.pipe(
  R.flatten,
  R.reduce(reducer, accumulator),
  ({pirate, pile_of_gold}) => ('count of pirates: ' + pirate + ' and the count of gold piles: ' + pile_of_gold)
);
Josep M Sobrepere
@josepot
Mar 17 2017 00:29
well, you will have to pipe it... first flatten, then the reduce, and then the string transformation.
In that way, I agree is uglier :smile:
Piet Vandeput
@piet-v
Mar 17 2017 00:30
:D
Josep M Sobrepere
@josepot
Mar 17 2017 00:31
Some people hate ternary operators... Specially if they are nested. I personally think that the formatting can help them be a lot more readable. Again, your original implementation seems pretty elegant :+1:
Piet Vandeput
@piet-v
Mar 17 2017 00:32
R.cond can come to the rescue though
lol, just saw a previous solution of someone else, he went plain javascript though :D
function secretMap(sp) {
  const getCount = (item) => sp.filter(v => v[0] === item).length;

  return `count of pirates: ${getCount('pirate')} and the count of gold piles: ${getCount('pile_of_gold')}`;
}
Denis Stoyanov
@xgrommx
Mar 17 2017 00:50
@piet-v
const secretMap2 = compose(
  ([pirates, gold]) => ('count of pirates: ' + pirates.length + ' and the count of gold piles: ' + gold.length), 
  map(defaultTo([])),
  props(['pirate', 'pile_of_gold']), 
  groupBy(identity))
James Forbes
@JAForbes
Mar 17 2017 00:56
@piet-v I think your original was good :D
Denis Stoyanov
@xgrommx
Mar 17 2017 00:59
const secretMap_ = lift((p, g) => `count of pirates: ${p} and the count of gold piles: ${g}`)(compose(length, filter(equals('pirate'))), compose(length, filter(equals('pile_of_gold'))))
Josep M Sobrepere
@josepot
Mar 17 2017 01:14
I like the latest one suggested by @xgrommx a lot. Although I would reformat it a little:
const getCountOf = prop => R.compose(R.length, R.filter(R.equals(prop)));
const getSecretMap = R.lift(
  (p, g) => `count of pirates: ${p} and the count of gold piles: ${g}`
)(
  getCountOf('pirate'), 
  getCountOf('pile_of_gold')
);
Denis Stoyanov
@xgrommx
Mar 17 2017 01:17
@josepot I have 1-line (doesn't matter) :smile:
Josep M Sobrepere
@josepot
Mar 17 2017 01:21
:joy: Well, sorry, I'm an "80 characters limit" nazi... I value short lines a lot, even if they make they increase the total number of lines.
but that's me
BTW: thanks a lot @xgrommx . Thanks to your code I've finally understood how lift works. :tada:
not that I've ever spend any time trying to figure it out, but a few time that I saw the function in the docs I was like: "what is this?" and I was like: "whatever, I probably don't need it". Now, I've seen the light.
Josep M Sobrepere
@josepot
Mar 17 2017 01:28
Question for @xgrommx : in the past I've used converge for accomplishing the same thing. Is there anything that can be done with liftthat can't be done with converge?
James Forbes
@JAForbes
Mar 17 2017 01:29

@josepot
I try to make the code on my blog render perfectly on a phone without any line wrapping/scrolling etc.

Which has led to me being a 40-50 character kind of guy :D

new lines are great if you don't like merge conflicts too
Denis Stoyanov
@xgrommx
Mar 17 2017 01:31
@josepot almost the same, converge can apply several arguments, but lift is applicative construction.
Josep M Sobrepere
@josepot
Mar 17 2017 01:32
then I think that perhaps the documentation should link them in the "See also", do you know what I mean?
Denis Stoyanov
@xgrommx
Mar 17 2017 01:33
@josepot converge works only with functions
Josep M Sobrepere
@josepot
Mar 17 2017 01:33
@xgrommx right!
now I get it, thanks @xgrommx
Denis Stoyanov
@xgrommx
Mar 17 2017 01:34
for example cartesian product
@ram-bot
liftN(2, unapply(identity))([1,2,3], [4,5,6])
Josep M Sobrepere
@josepot
Mar 17 2017 01:36
@JAForbes short lines are great for readability... but I also have a selfish reason: I work a lot in my laptop and I use vim, I usually have 3 vertical splits... So short lines are perfect for my workflow. Not the strongest argument, but I have to admit that I became a lot more intolerant with long lines when I started working with vim...
That's awesome! I get it now @xgrommx . Thanks a lot!
Denis Stoyanov
@xgrommx
Mar 17 2017 01:37
@josepot liftA2 => ap(map(x => y => [x, y], [1,2,3]), [4,5,6]) liftA3 = liftA2 + ap and etc
in haskell it is really nicely :smile: s <$> fn <*> s1 <*> s2 <*> ...
Jonah
@jonahx
Mar 17 2017 02:25
@xgrommx thanks, though it still feels too long and complicated for what it is. the distance between thought and code is too wide. compare the solution in J: ,.(+/@(={:)\)
Jonah
@jonahx
Mar 17 2017 03:20
Here’s one more alternative:
converge(zip, [
  identity,
  pipe(
    scan(flip(append), []),
    tail,
    map(x => filter(equals(last(x)), x)),
    map(length)
  )
])
Jonah
@jonahx
Mar 17 2017 04:01
It gets a little nicer if you break out some reasonable utility functions:
const scans = pipe( scan(flip(append), []), tail );
const frequencyOf = curry(
  (pickFn, xs) => filter(equals(pickFn(xs)), xs).length
);
const occurenceCounts = pipe( scans, map(frequencyOf(last)) );

const withOccurenceCounts = converge(zip, [identity, occurenceCounts]);
Adam Szaraniec
@mimol91
Mar 17 2017 10:58
how can I cast to bool in ramda?
Aldwin Vlasblom
@Avaq
Mar 17 2017 11:22
@ram-bot map(Boolean, [0, 1, 2])
Raine Virta
@raine
Mar 17 2017 11:52
sorry, the vps bot is on is dead. i've put it somewhere else for now
@ram-bot status
ram-bot
@ram-bot
Mar 17 2017 11:53
All systems operational.
Robert Mennell
@skatcat31
Mar 17 2017 15:53
I swear I think I've read this before, but the reason Ramda calls map on things instead of fmap is because it's more familiar to javascript coders, right?
See the link in the edit
Robert Mennell
@skatcat31
Mar 17 2017 17:09
@gabejohnson So what I'm getting from that is that basically says Haskell has map and fmap, and at first just had map on everything, then went and changed it so "it was easier for beginners to realize they screwed up on something", but that everyone really just wants map. So it was supposed ot be map, but someone said "Let their be confusion and hopefully better error messages!" and thus came about fmap?
Gabe Johnson
@gabejohnson
Mar 17 2017 17:11
I think it had map on Lists and then generalized it to Functors
but to do it over again would prbly call fmap map
Robert Mennell
@skatcat31
Mar 17 2017 17:12
that's what the consensus is. The best solution they seem to have come up with in mailing list(found in that stackoverflow thread, thanks) is that they should go about depreciating fmap by defining map, and redoing fmap in terms of it on functors
but from what comes after I have no idea
the final resting place of why fmap and map exist in haskel
Gabe Johnson
@gabejohnson
Mar 17 2017 17:22
I don't think PureScript has fmap
So to answer your original question I would say because fmap is unnecessary and confusing
Robert Mennell
@skatcat31
Mar 17 2017 17:23
:+1:
Johnny Hauser
@m59peacemaker
Mar 17 2017 18:11
What's the word for the relationship between fromFoo and toFoo?
input === fromFoo(toFoo(input))
Matthew Willhite
@miwillhite
Mar 17 2017 18:18
natural transformation?
isomorphism?
Robert Mennell
@skatcat31
Mar 17 2017 18:19
It looks like complimentary transformers?
Johnny Hauser
@m59peacemaker
Mar 17 2017 18:19
I think isomorphic
I never really understood that word before so I'm not sure =D
Matthew Willhite
@miwillhite
Mar 17 2017 18:19
This is isomorphic (taking from Dr. Boolean’s egghead lesson)
// from(to(x)) == x
// to(from(y)) == y
and natural transformation: // nt(x).map(f) == nt(x.map(f))
Robert Mennell
@skatcat31
Mar 17 2017 18:23

isomorphic: of similar structure

const fromInt = x => {int:x}
const toInt = x => x.int
toInt(fromInt(5)) == 5

another example would be fromCharCode and charChodeAt which can be composed to get back the original character from a string at an index

Johnny Hauser
@m59peacemaker
Mar 17 2017 18:24
Does my test make sense, then? (it does pass)
test('qs.parse and qs.stringify are isomorphic', function (t) {
  t.deepEqual(
    qs.parse(qs.stringify({a: 'a'})),
    {a: 'a'}
  )
})
Robert Mennell
@skatcat31
Mar 17 2017 18:24
JSON.parse and JSON.stringify are isomorphic, yes
Johnny Hauser
@m59peacemaker
Mar 17 2017 18:25
mine is query string
but yeah, I'm just making sure I get it
Quite simple for such an intimidating word!
Robert Mennell
@skatcat31
Mar 17 2017 18:25
tow functions are considered isomorphic IFF F(f(x)) == f(F(x)) == xmeaning in mathematical terms f == inverese F && F == inverse f. An example being exponants and logarithms for math terms
Robert Mennell
@skatcat31
Mar 17 2017 18:30
for REALLY confusing example: not in boolean is the invertor operator(!) is isomorphic to itself ( ! ! TRUE && TRUE ) XD
Johnny Hauser
@m59peacemaker
Mar 17 2017 18:31
haha
Robert Mennell
@skatcat31
Mar 17 2017 18:32
If you want a real(er) example: trigonometry
Johnny Hauser
@m59peacemaker
Mar 17 2017 18:39
Thanks!
Robert Mennell
@skatcat31
Mar 17 2017 18:44
@m59peacemaker reminder: don't get Algebra confused with algebras
Rick Medina
@rickmed
Mar 17 2017 19:45
compose(g, h) = id
Izhaki
@Izhaki
Mar 17 2017 23:34
Any practical or theoretical explanation to why the aggregator in mapAccum returns a tuple, and why the final returned value includes the final accumulator?