These are chat archives for ramda/ramda

24th
Apr 2017
Jonah
@jonahx
Apr 24 2017 06:29

Interesting problem I can’t find a great functional solution for, but which feels like it should be a one liner. You’re given an array of words, and must break them into lines, where each line has a specified max character length and where spaces between words count toward that length (ie, the function’s type is [String] -> Int -> [[String]]). eg, given a max line length of 13, an array containing the individual words "a quick brown fox jumps over the lazy dog" would break down into 4 line arrays:

[
  ["a", "quick", "brown”], // <— NB: exactly 13 characters (bc two spaces between words)
  ["fox", "jumps"],
  ["over", "the", "lazy"],
  ["dog"]
]

Can you solve this without using reduce?

Martin Broder
@mrtnbroder
Apr 24 2017 10:06
Hey folks, how do you use concat with more than two arguments?
Bohdan Ganicky
@bganicky
Apr 24 2017 10:09
@mrtnbroder R.reduce(R.concat, [], [[1, 2], [3, 4], [5, 6]])
Martin Broder
@mrtnbroder
Apr 24 2017 10:10
ah, neat :)
Kurt Milam
@kurtmilam
Apr 24 2017 10:11
@mrtnbroder And if you don't want to pass in an array of arrays, you can do it like this: const concatM = ( ...args ) => R.reduce( R.concat, [], args )
This can be called like concatM( [1, 2], [3, 4], [5, 6] )
Martin Broder
@mrtnbroder
Apr 24 2017 10:13
I'd maybe call it concatMany explicitly, otherwise M may be misinterpreted as Monad or something :)
thanks!
Stephan Meijer
@smeijer
Apr 24 2017 10:17
Is there a Ramda util for (x, y) => y ?
Martin Broder
@mrtnbroder
Apr 24 2017 10:19
ah sory
Martin Broder
@mrtnbroder
Apr 24 2017 10:20
R.last @smeijer ?
though I'd just write it myself const snd = (_, y) => y
that's how haskell calls it aswell
Denis Stoyanov
@xgrommx
Apr 24 2017 10:25
@mrtnbroder [].concat(...[[1, 2], [3, 4], [5, 6]])
@mrtnbroder unapply(head), unapply(last)
Martin Broder
@mrtnbroder
Apr 24 2017 10:26
@xgrommx in basic js I can even write [].concat([1,2], [3,4], [5,6])
Denis Stoyanov
@xgrommx
Apr 24 2017 10:29
@mrtnbroder chain(identity)([[1, 2], [3, 4], [5, 6]])
Stephan Meijer
@smeijer
Apr 24 2017 10:32
I go with the snd option, just leave the lambda. Better keep it readable
Denis Stoyanov
@xgrommx
Apr 24 2017 10:33
@smeijer make your own Tuple
Martin Broder
@mrtnbroder
Apr 24 2017 10:37
does someone have an Idea how I can rewrite this function to get rid of the repeated calls to R.map?
const mod = ({ users, dogs, cats, hamsters }) => [].concat(
R.map(modifier('users'), users),
R.map(modifier('dogs'), dogs),
R.map(modifier('cats'), cats),
R.map(modifier('hamsters'), hamsters),
))
"repeated" in the sense of staying DRY.
Denis Stoyanov
@xgrommx
Apr 24 2017 10:39
@mrtnbroder what is your goal?
Martin Broder
@mrtnbroder
Apr 24 2017 10:40
removing some lines of code
you can see the pattern here
Kurt Milam
@kurtmilam
Apr 24 2017 10:41
Pass in ({ ...args }) and map args?
Although I see that might not 100% get you there on review.
Martin Broder
@mrtnbroder
Apr 24 2017 10:41
yeah cause of the individual keys
Denis Stoyanov
@xgrommx
Apr 24 2017 10:43
@mrtnbroder please provide code with examples I need to run it
Kurt Milam
@kurtmilam
Apr 24 2017 10:47
change your params definition to the following and map over x:
( x = { users, dogs, cats, hamsters } )
Inside the function, x will be { users, dogs, cats, hamsters }
Martin Broder
@mrtnbroder
Apr 24 2017 10:51
@xgrommx https://goo.gl/XMtSKc basically this
Kurt Milam
@kurtmilam
Apr 24 2017 10:53
Just don't destructure myObj, then map over it. You'll have the object keys and values.
@mrtnbroder in other words, change the argument definition for mod from const mod = ({ users, dogs, cats, hamsters }) => to const mod = container => and map over container's keys and values inside mod.
You're unnecessarily throwing away necessary information (the obect's keys) by destructuring in this case.
Bohdan Ganicky
@bganicky
Apr 24 2017 11:34
@mrtnbroder https://goo.gl/bzWX6C
Martin Broder
@mrtnbroder
Apr 24 2017 11:40
@kurtmilam true!
can use R.mapObjIndexed!
Denis Stoyanov
@xgrommx
Apr 24 2017 11:46
@mrtnbroder how?
Martin Broder
@mrtnbroder
Apr 24 2017 11:49
I've rewritten the whole function definition so it works with mapObjIndexed
Denis Stoyanov
@xgrommx
Apr 24 2017 11:49
@mrtnbroder example?)
Martin Broder
@mrtnbroder
Apr 24 2017 11:49
note the output is different
but that's okay since I use it differently than before now
Denis Stoyanov
@xgrommx
Apr 24 2017 11:50
@mrtnbroder my version compose(flatten, values, mapObjIndexed((value, key) => map(assoc('source', key), value)))(myObj)
Martin Broder
@mrtnbroder
Apr 24 2017 11:51
that's also a variant :D
btw, thanks for the quora link!
may I ask what you use this for @xgrommx ? https://github.com/xgrommx/practical-functional-programming, is this like your utility-belt?
Denis Stoyanov
@xgrommx
Apr 24 2017 11:52
@mrtnbroder just for fun
Martin Broder
@mrtnbroder
Apr 24 2017 11:53
nice, gonna :eyes: it
Denis Stoyanov
@xgrommx
Apr 24 2017 11:54
@mrtnbroder I'll add monad transformers and other nice stuff
Martin Broder
@mrtnbroder
Apr 24 2017 11:54
you mean soon?
Denis Stoyanov
@xgrommx
Apr 24 2017 11:55
@mrtnbroder yes
@mrtnbroder maybe recursion schemes with several nice examples (I'll rewrite my haskell examples) :smile:
Martin Broder
@mrtnbroder
Apr 24 2017 11:56
nice! now with v8's tail-optimization that can come in handy :tada:
Martin Broder
@mrtnbroder
Apr 24 2017 12:04
is that how you implemented laziness?
Denis Stoyanov
@xgrommx
Apr 24 2017 12:05
@mrtnbroder yes, for ZipList we need infinity list for of
Martin Broder
@mrtnbroder
Apr 24 2017 12:17
neat!
where can I find your haskell examples @xgrommx ? :D
Denis Stoyanov
@xgrommx
Apr 24 2017 12:28
@mrtnbroder now, only on my laptop :smile:
Stefano Vozza
@svozza
Apr 24 2017 13:02
@mrtnbroder is tco in the V8 not behind a flag anymore?
Rick Medina
@rickmed
Apr 24 2017 13:09
@jonahx unfold?
I don't care about anything in js other than recursion optimizations :)
Gabe Johnson
@gabejohnson
Apr 24 2017 13:17
@mrtnbroder the Haskell function you linked to has to be passed a Tuple.
@smeijer What you want is something like flip(always)
But writing it by hand is trivial
Martin Broder
@mrtnbroder
Apr 24 2017 13:30
@gabejohnson well yeah, but in js we have arguments, so he can either go with ([x, y]) => y or (x, y) => y, his decision :)
or even Tuple.snd()
Gabe Johnson
@gabejohnson
Apr 24 2017 13:34
@mrtnbroder but he didn't appear to be dealing with a tuple, he just wanted a function that returned the second argument
but flip(always) doesn't work
Denis Stoyanov
@xgrommx
Apr 24 2017 13:39
@gabejohnson why ? :smile:
Gabe Johnson
@gabejohnson
Apr 24 2017 13:40
@xgrommx well it does, but you have to do flip(always)(x,y)()
It works the way I expected w/ Sanctuary's K combinator
Jesus
@jefe-spain
Apr 24 2017 13:40
hello guys, is this function pure? const active = (window, site) => site === 'testSite' && window.location.href.indexOf('mobile-phones') === -1
Gabe Johnson
@gabejohnson
Apr 24 2017 13:41
@jefe-spain no
wait
Jesus
@jefe-spain
Apr 24 2017 13:41
in that case, what’s wrong with it
:)
Gabe Johnson
@gabejohnson
Apr 24 2017 13:41
you passed in window
Jesus
@jefe-spain
Apr 24 2017 13:42
yes
Gabe Johnson
@gabejohnson
Apr 24 2017 13:42
didn't notice that
The value of window.location.href.indexOf('mobile-phones') won't necessarily be the same every time you call the function w/ the same arguments
if window were immutable it would be a different story
@jefe-spain so I would say no
Denis Stoyanov
@xgrommx
Apr 24 2017 13:46
@gabejohnson as u know it doesn't work in original K combinator, arity should be only 1
Jesus
@jefe-spain
Apr 24 2017 13:46
so, in that case, @gabejohnson , how you would make it pure?
Gabe Johnson
@gabejohnson
Apr 24 2017 13:46
@xgrommx correct
Jesus
@jefe-spain
Apr 24 2017 13:46
as every time we use the DOM/Window we r playing in a mutable world
Gabe Johnson
@gabejohnson
Apr 24 2017 13:47
@jefe-spain you could pass window.location.href instead of window
Jesus
@jefe-spain
Apr 24 2017 13:48
:thumbsup: That’s sound better!
Gabe Johnson
@gabejohnson
Apr 24 2017 13:48
const active = (href, site) =>
  site === 'testSite' && href.indexOf('mobile-phones') === -1;
Gabe Johnson
@gabejohnson
Apr 24 2017 13:53
@jefe-spain even better would be
const validateSite = (hrefSegment, siteName) =>
  (href, site) => site === siteName && href.includes(hrefSegment);
reusable
Jesus
@jefe-spain
Apr 24 2017 13:54
hrefSegemts, where that coming from?
Gabe Johnson
@gabejohnson
Apr 24 2017 13:55
const active = validateSite('mobile-phones', 'testSite');
Jesus
@jefe-spain
Apr 24 2017 13:57
it woudl be -> const active = validateSite(‘mobile-phones’, ‘testSite’)(window.location.href)
as the second site from (href, site), we dont’ need it isnt it?
Gabe Johnson
@gabejohnson
Apr 24 2017 14:01
@jefe-spain siteName replaces 'testSite' in your example
if you want to use the function in the future with a different site name you can change it
you still need to compare site w/ siteName
but it's trivial to write so reusability probably isn't a big deal
It's a good habit to get into though
Mick Dekkers
@mickdekkers
Apr 24 2017 19:35
Is there a function similar to R.evolve that drops the keys that don't have a transformation function?
Matthew Willhite
@miwillhite
Apr 24 2017 19:45
@ram-bot
const ts = {
  foo: inc,
  bar: dec
}

const o = {
  foo: 1,
  bar: 1,
  baz: 'x'
}

const survivalOfTheFittest = converge(pick, [keys, evolve])(ts)

survivalOfTheFittest(o)
ram-bot
@ram-bot
Apr 24 2017 19:45
{ foo: 2, bar: 0 }
Mick Dekkers
@mickdekkers
Apr 24 2017 19:50
@miwillhite Nice! Thanks :)
Malgalad
@Malgalad
Apr 24 2017 20:41

Hi guys. I'm doing a little skill-up project, and as a part of it I try to learn FP.
So, here's a function that I'm trying to convert to Ramda:

var buildDistributions = function(m, n) {
    var lineGroups = [];
    var lines = [];
    var points, i, j;

    for (j = 0; j < n; j++) {
      lines.push(['a', 'b']); // not actual values
    }
    lineGroups.push(lines);

    for (i = 1; i < m; i++) {
      lines = [];
      for (j = 0; j < n; j++) {
        lines.push(['c', 'd']); // not actual values, dynamically generated
      }
      lineGroups.push(lines);
    }

    lines = [];
    for (j = 0; j < n; j++) {
      lines.push([[0, 0], [1,0]]);
    }
    lineGroups.push(lines);

    return lineGroups;
  };

That's some oldish code, but it does what it needs to do so whatever. Here is what I've come to:

const seq_1 = ['a', 'b'];
const seq_2 = ['c', 'd'];

const f1_0 = compose(repeat(seq_1), nthArg(1));
const f1 = converge(repeat(__, 1), [f1_0]);  // actually I just need to do wrap result of fn1_0 in array,  (...args) => [fn1_0(...args)]

const f2_0 = compose(repeat(seq_2), nthArg(1));
const f2 = converge(repeat, [f2_0, dec]);

But then I'm stuck. What I want to do is (n, m) => [].concat(f1(n, m), f2(n, m), f1(n, m)), but Ramda's concat has arity of 2.
So I tried (1)

const f3_1 = converge(concat, [f1, f2]);
const f3 = converge(concat, [f3_1, f1]);

But that seems a bit excessive. So I tried to use good old reduce and came to (2)

const f3_1 = (n, m) => (acc, fn) => concat(fn(n, m), acc);
const f3 = converge(reduce(__, [], [f1, f2, f1]), [f3_1]);

but now I have no idea what to do with f3_1...

concatMany may help you further
Malgalad
@Malgalad
Apr 24 2017 20:51
Many thanks, @mrtnbroder, that did the trick.
Brad Compton (he/him)
@Bradcomp
Apr 24 2017 20:52
@ram-bot
const fillOne = () => ['a', 'b'];
const fill2 = () => ['c', 'd'];
const fill3 = () => [[0, 0], [0, 1]];
times(10, fillOne).concat(times(5, times(10, fill2))).concat(times(10, fill3));
ram-bot
@ram-bot
Apr 24 2017 20:52
n must be a non-negative number
Brad Compton (he/him)
@Bradcomp
Apr 24 2017 20:52
:expressionless:
Malgalad
@Malgalad
Apr 24 2017 20:53
fill3 is actually fillOne, forgot to replace it there as well
Brad Compton (he/him)
@Bradcomp
Apr 24 2017 20:54
Malgalad
@Malgalad
Apr 24 2017 20:55
Close, but not actually right... Results of times(10, fillOne) should be in array. Caught be off guard too, spent quite a while debugging...
Brad Compton (he/him)
@Bradcomp
Apr 24 2017 20:59
nvm