These are chat archives for ramda/ramda

8th
Aug 2016
Martin Broder
@mrtnbroder
Aug 08 2016 07:34
Hey folks
I wonder, what would be a 'nice' way to translate errors messages with the following format:
const reason = {
  status: 'error',
  errors: [{
    code: 123,
    description: 'Error description',
    name: 'Error Name'
  }, ...]
}
where I take the code as an input for my conditional and transform the description
currently, I have the following:
const codeToDescription = ({ code, ...props }) => ({ ...props, code, description: translateCode(code) })

export const translateError = ({ errors, ...props }) => ({ ...props, errors: map(codeToDescription)(errors) })

translateError(reason)
translateCode is just a big conditional.
Scott Christopher
@scott-christopher
Aug 08 2016 09:12
@mrtnbroder Are you wanting to refactor the code you posted there, or looking for advice on how to implement translateCode?
Denis Stoyanov
@xgrommx
Aug 08 2016 09:27
pretty easy arrayEqual, intersection and difference with filter map and find from standard js
const arrayEqual = a => b => p => a.length === b.length && a.every((x, ix) => b.find((y, iy) => p(x, y) && ix === iy));
const intersect = a => b => p => a.filter((x, ix) => !!b.find((y, iy) => p(x, y)));
const difference = a => b => p => b.filter((x, ix) => !a.find((y, iy) => p(x, y)) && x);



let [a, b] = [[1,2,3], [3,2,1,4,6,7,8,8]];

console.log(arrayEqual(a)(b)((x, y) => x === y));
console.log(intersect(a)(b)((x,y) => x === y));
console.log(difference(a)(b)((x,y) => x === y));
zip
const zip = (...xs) => fn => [...Array(Math.min(...xs.map(x => x.length)))].map((_, i) => fn(...xs.map(x => x[i])))
console.log(zip([1, 2, 3], [4, 5, 6, 10], [7, 8, 9], [3, 5])((...args) => args));
Martin Broder
@mrtnbroder
Aug 08 2016 10:43
@scott-christopher refactor/improvements ;)
James Grayling
@jamesgrayling
Aug 08 2016 10:58
const translateError = applySpec(
{ props: prop( 'props' )
, errors: map(prop( 'errors' ), codeToDescription)
})
This message was deleted
This message was deleted
James Grayling
@jamesgrayling
Aug 08 2016 11:12
Actually that doesn't work...
James Grayling
@jamesgrayling
Aug 08 2016 11:18
@mrtnbroder http://goo.gl/Eyt8o6
Denis Stoyanov
@xgrommx
Aug 08 2016 11:28
almost pointfree
var xs = [[1,2,3], [4,5,6,7,8,9,6,7,8]];

const zipArray = fn => lift(call)(
  B(B(map)(converge(fn)))(map(flip(nth))), 
  compose(range(0), lift(reduce(min))(head, tail), map(length))
);

zipArray(add)(xs)
Bravi
@Bravilogy
Aug 08 2016 11:31
I wish there was a site with ramda.js examples. actual, working examples from people's codes
Barney Carroll
@barneycarroll
Aug 08 2016 11:31
@Bravilogy for a while I've been thinking of a beefed up community edition of the documentation
Bravi
@Bravilogy
Aug 08 2016 11:32
@barneycarroll it would be so much easier to learn
Barney Carroll
@barneycarroll
Aug 08 2016 11:32
It would extend each API with a synonyms section
And search would be conscious of that
And also have a kind of 'popular examples' thing
Bravi
@Bravilogy
Aug 08 2016 11:34
documentation is really good and the repl helps a lot as well. but let's face it - there are tons of functions :D and tons of possibilities of doing certain things. it would be cool to have just random examples from everyone who wants to contribute. even if it's a small, 3 line code
@barneycarroll for searching, we could have tags for each example. Whatever ramda function you use, u tag it
Martin Broder
@mrtnbroder
Aug 08 2016 11:40
guys
just contribute :)
Barney Carroll
@barneycarroll
Aug 08 2016 11:46
Functional programmers love consistent, easily traversible data structures
Like wikis ;P
Artur
@ArturAralin
Aug 08 2016 11:48
Hi all! How to realise it in ramda?
function generateId(ids) {
  var id = randomstring.generate(ID_LENGTH);

  return ids.has(id) ? generateId(ids) : id;
}
Martin Broder
@mrtnbroder
Aug 08 2016 12:07
what do you think of this @jamesbrown0
http://goo.gl/qXE3nO
Martin Broder
@mrtnbroder
Aug 08 2016 12:14
so I don't have to care about explicitly propagating all props of the object
James Grayling
@jamesgrayling
Aug 08 2016 12:36
That looks more sensible, @mrtnbroder, but why did you use useWith(identity)? That does precisely nothing
Martin Broder
@mrtnbroder
Aug 08 2016 12:37
it does
it returns the whole object
which is what I want
oh wait
actually youre right
James Grayling
@jamesgrayling
Aug 08 2016 12:39
You've just composed your function with identity in a verbose manner
Martin Broder
@mrtnbroder
Aug 08 2016 12:39
sorry totally forgot about that
Tim Navrotskyy
@dypsilon
Aug 08 2016 12:40
Hi everyone, do you know of any good tutorials or articles about tree traversal in functional programming? folds, catamorphisms, f-algebras, recursion, corecursion etc.. anything would help. Preferably with JavaScript examples. I see alot of Haskell or Scala material, but, sadly, no JS...
Rafe
@rjmk
Aug 08 2016 12:41
@dypsilon I love this article
James Grayling
@jamesgrayling
Aug 08 2016 12:49
@mrtnbroder Instead of using assocPath([ 'description ]), you can use assoc( 'description' )
Martin Broder
@mrtnbroder
Aug 08 2016 12:49
i know
I was thinking about making a more generic version
thats why I used assocPath first
James Grayling
@jamesgrayling
Aug 08 2016 12:52

You could cut it down to this if you don't need that:

const codeToDesc =
  err => assoc( 'description' , translate(err.code))(err)
const translateReason = evolve({
  errors: map(codeToDesc)
})

and you can make codeToDesc point-free...

Michael D. Stemle, Jr.
@manchicken
Aug 08 2016 13:08
R.compose() allows currying, yeah?
James Grayling
@jamesgrayling
Aug 08 2016 13:11
Yeah, you can do that but maybe not a good idea:
const translate = toString 
const codeToDesc =
  converge( assocPath
  , [ identity
    , compose( translate, flip(prop( 'code' )))
    , flip(identity)
    ])
const translateReason = evolve({
  errors: map(codeToDesc(['description']))
})
@mrtnbroder
Martin Broder
@mrtnbroder
Aug 08 2016 13:11
that looks even more nasty
I'm happy with what I have right now
thanks!
James Grayling
@jamesgrayling
Aug 08 2016 13:12
@manchicken From the docs: Note: The result of compose is not automatically curried.
Michael D. Stemle, Jr.
@manchicken
Aug 08 2016 13:12
@jamesbrown0 I’m more thinking about inputs.
And it’s totally possible that I’m doing it wrong.
James Grayling
@jamesgrayling
Aug 08 2016 13:14
I'm not sure what you mean. The first function in a composition can take any number of argument. All the others can only take one.
Michael D. Stemle, Jr.
@manchicken
Aug 08 2016 13:14
OOH! I get what you mean. Sorry.
Still new to things.
(FP things)
James Grayling
@jamesgrayling
Aug 08 2016 13:16
You can use curried functions in a composition:
compose( prop( 'bar' ), prop('foo' ))
As long as the functions accept one more argument
Michael D. Stemle, Jr.
@manchicken
Aug 08 2016 13:18
Yeah, your statement helped me see that I was doing this wrong. Thanks :)
Denis Stoyanov
@xgrommx
Aug 08 2016 13:20
var useWith2 = curry((fn, transformers) => curryN(transformers.length, unapply(compose(apply(fn), zipWith(call, transformers)))));
Bravi
@Bravilogy
Aug 08 2016 14:05
I'm trying to replace multiple placeholders at once. Can this not be done by using R.replace?
let template = 'You message "{message}" has been sent to {name}';

const buildMessage = R.replace(R.match(/{[a-zA-Z]+}/g, template), R.__, template);

buildMessage(['hello', 'John']);
doesn't seem to work
Denis Stoyanov
@xgrommx
Aug 08 2016 14:41
@Bravilogy try smth like this one
let template = 'You message "{message}" has been sent to {name}';

var patterns = match(/{[a-zA-Z]+}/g)(template);
var replacers = ['Hello', 'World'];

addIndex(reduce)((a, b, i) => replace(b, replacers[i], a))(template)(patterns)
James Forbes
@JAForbes
Aug 08 2016 14:46

You could probably zip the matches with the input as well.

let template = 'You message "{message}" has been sent to {name}';

R.zip(R.match(/{\w+}/g, template), ['hello', 'John'])
.reduce(
  (p,n) => p.replace(...n)
  ,template
)

But you'd need to massage it a bit to get it point free

Bravi
@Bravilogy
Aug 08 2016 15:01
@xgrommx that almost works. it leaves out {message} but replaces {name}
this is a mind twister :D
damn!
Bravi
@Bravilogy
Aug 08 2016 15:28
Ok I'm very close now to making it point free I think:
const buildMessage = (type, data) => {
   let message = messages[type],
         placeholders = getPlaceholders(message);

   return R.addIndex(R.reduce)((msg, placeholder, i) => R.replace(placeholder, data[i], msg))(message)(placeholders);
};

This works:

const getPlaceholders = R.pipe(
    R.flip(R.prop)(messages),
    R.match(/{[a-zA-Z]+}/g)
);

const buildMessage = (type, data) => R.addIndex(R.reduce)((msg, placeholder, i) => R.replace(placeholder, data[i], msg))(messages[type])(getPlaceholders(type));

But it's not that readable I think :D

Pavel Meledin
@btbvoy
Aug 08 2016 18:50
Hello everyone! Could somebody share a link to source code of a project which is completely or mostly done using ramda? I want to see some work which is done using FP way using this library
here you go
@rjmk thanks, that's a good one, I will give it a read...
Pavel Meledin
@btbvoy
Aug 08 2016 20:49
@dypsilon thanks a lot