These are chat archives for ramda/ramda

9th
Mar 2017
Nate Shoemaker
@nshoes
Mar 09 2017 00:01
quick question
why is this compose(objOf(key), call, path(['mapLocation', key]))
not equivalent to this compose(objOf(key), call(path(['mapLocation', key])))
Brad Compton (he/him)
@Bradcomp
Mar 09 2017 00:02
R.call
Brad Compton (he/him)
@Bradcomp
Mar 09 2017 00:03
What gets passed to call is different in each case
So in the first case, path takes the parameters provided, and the result of that is passed to call
But in the second case, the parameters provided are passed directly to call(path(...))
Nate Shoemaker
@nshoes
Mar 09 2017 00:04
oh hello
thank you :]
Robert Mennell
@skatcat31
Mar 09 2017 00:04
apparently typescript doesn't like manual currying through branching
// Just some fun
function add(a, b) {
    if (b) {
        return Number(a) + Number(b);
    }
    return function (b) {
        return Number(a) + Number(b);
    };
}
console.log(add(1)(2), add(2, 3));
Robert Mennell
@skatcat31
Mar 09 2017 00:17
Actually that brings up the exact question I'm currently having fun with: What different ways of currying are there?
I know there is:
  • Manual required
    const fn = a => b => a + b;
  • Manual branching
    function add(a, b) {
     if (b) {
         return Number(a) + Number(b);
     }
     return function (b) {
         return Number(a) + Number(b);
     };
    }
  • automatic arity
    ramda implimentation
  • none
    js default
Raine Virta
@raine
Mar 09 2017 00:59
added treis as well, hopefully doesn't end up generating too much output (= spam)
@ram-bot R.reduce(treis(R.multiply), 1, [1, 2, 3])
ram-bot
@ram-bot
Mar 09 2017 00:59
6

output

f2 a: 1
   b: 1
f2 => 1
f2 a: 1
   b: 2
f2 => 2
f2 a: 2
   b: 3
f2 => 6
Jonas Windey
@jonaswindey
Mar 09 2017 07:36

anyone knows why this is working:

const mapMeasure = (data, definition, mapMethod) => map(measure => ({
  measure,
  months: pipe(
    map(month => mapMethod(month, data, definition)(measure)),
    reduce((result, item) => ({...result, [item.month]: item.value}), {})
  )(months)
}))

but why I can't send measure to the pipe function? (mapMethod is curried)

const mapMeasure = (data, definition, mapMethod) => map(measure => ({
  measure,
  months: pipe(
    map(month => mapMethod(month, data, definition)),
    reduce((result, item) => ({...result, [item.month]: item.value}), {})
  )(months, measure)
}))
Gabe Johnson
@gabejohnson
Mar 09 2017 11:52
@jonaswindey map(fn)only takes a single argument
Bernhard Wang
@zwc
Mar 09 2017 15:02
I'm stuck with trying to use defaultTo together with path. All I want to do is to return false instead of undefined if property is not found. Anyone have an idea on how to get it working?
const R = require('ramda');
const expect = require('chai').expect;

const obj = {
    level1: {
        level2: {
            level3: 'deep'
        }
    },
    nested: {
        prop: {
            binary: true
        }
    }
};

const defaultPath = R.useWith(R.path, [R.split('.')]);

expect(defaultPath('level1.level2.level3')(obj)).to.equal('deep');
expect(defaultPath('nested.prop')(obj)).to.eql({ binary: true });
expect(defaultPath('does.not.exist').to.eql(false));
Gabe Johnson
@gabejohnson
Mar 09 2017 15:19
@zwc you could use pathOr
or compose defaultTo(false) and path
Bernhard Wang
@zwc
Mar 09 2017 15:29
I'll give it a try :)
Galileo Sanchez
@galileopy
Mar 09 2017 15:29
how can I omit the function wrapper?
parse = (example) =>R.apply(Message, R.ap(R.ap([Field.parser], Grammar), [example]))
Stephan Meijer
@smeijer
Mar 09 2017 15:38
curry ?
Galileo Sanchez
@galileopy
Mar 09 2017 15:38
solved it like this
Message.parser = R.useWith(R.ap(R.ap([Field.parser], Grammar)), [R.of]);
Message.parse =  R.useWith(R.apply(Message), [Message.parser]);
Gabe Johnson
@gabejohnson
Mar 09 2017 15:41
@galileopy
Message.parse = R.compose(R.apply(Message), R.compose(R.ap(R.ap([Field.parser], Grammar)), R.of))
?
Galileo Sanchez
@galileopy
Mar 09 2017 15:47
excellent, much better, thanks!!
Gabe Johnson
@gabejohnson
Mar 09 2017 15:48
I don't know if it's better...I would break it up w/ a helper
Denis Stoyanov
@xgrommx
Mar 09 2017 15:48
I was later :smile:
Bravi
@Bravilogy
Mar 09 2017 16:46
hey guys, is there a way to unnest and object 1 level? for example
const fn = (obj) => { /* some awesomeness */ };
const a = {
   b: {
      hello: 'world'
   }
};
fn(a);
// => { hello: 'world' }
actually that's a mistake
and I just realised that I'm trying to achieve a simple spread {...obj}
damn it.
Nate Shoemaker
@nshoes
Mar 09 2017 17:27
:)
Robert Mennell
@skatcat31
Mar 09 2017 17:34
Okay maybe I'm not thinking right because of lack of sleep, but by spread object operator, you mean something like:
let { ...internal} = { b: { hello : 'world' } }
console.log(internal)
// { hello : 'world'}
Bravi
@Bravilogy
Mar 09 2017 17:35
yeah exactly
Robert Mennell
@skatcat31
Mar 09 2017 17:36
okay. Just don't forget it will create an object of every internal key not mentioned. I did that yesterday and kept trying to figure out where the hell this other key in the spread was coming from -.-
Bravi
@Bravilogy
Mar 09 2017 18:03
is there a without function for objects? For example
const user = {
   firstName: 'John',
   lastName: 'Smith',
};
withoutProp('lastName', user);
// => { firstName: 'John' }
@ram-bot dissoc('lastName', {firstName: 'John', lastName:'Smith'})
ram-bot
@ram-bot
Mar 09 2017 18:11
{ firstName: 'John' }
Matthew Willhite
@miwillhite
Mar 09 2017 18:12

Just shooting in the dark:

var withoutProp = curry((keys, val, key) => complement(contains)(key, keys));
pickBy(withoutProp(['firstName']), { firstName: 'John', middleName: 'J', lastName: 'Smith’})

// {"lastName": "Smith", "middleName": "J”}

If you want to be able to select which keys to exclude, and leave the rest

Robert Mennell
@skatcat31
Mar 09 2017 18:17
with dissoc you can pipe them so that you can remove whatever properties you don't want:
const removeID = R.dissoc('id')
const removePassword = R.dissoc('password')
const makeSafeUser = R.pipe( removeID, removePassword)

return makeSafeUser(user)
pipe or compose will both work here
Matthew Willhite
@miwillhite
Mar 09 2017 18:18
:thumbsup:
Bravi
@Bravilogy
Mar 09 2017 18:19
thanks guys

source code. If object size is a concern, you can always just delete from the object

const removeProp = Curry(( prop, o ) => { delete o[prop]; return o })
const removeID = removeProp('id')
const removePass = removeProp('password')
const makeSafeUser =...

while this will perform better(pointer manipulation instead of cloning), it breaks the immutability clauses of FP. In some cases this may be desired( large object structures )
You should note that in your code if yo udo decide to do such

Nate Shoemaker
@nshoes
Mar 09 2017 18:24
is there a roadmap for ramda getting to 1.0?
Galileo Sanchez
@galileopy
Mar 09 2017 18:48
@gabejohnson that's what I did and parametrized the grammar and language too since that fn is used extensively
I'm checking union-type I have some data fields that can only a be in small set of values, but I don't know how to use it to fit my case
Galileo Sanchez
@galileopy
Mar 09 2017 18:54
I think what I want to do is not supported actually, something like typeof Type({n: [ isNumber], s: [isString]})(5) === 'n')
Robert Mennell
@skatcat31
Mar 09 2017 18:54
@nshoes with semver you can look at it more of: 0 breaking API changes .23 new feature additions and .0 patches, so ifyou go back to the re versioning of old, this would be version 1.23.0... at least that's the way I look at it
Drew
@dtipson
Mar 09 2017 22:14
@xgrommx yes! When I was starting out playing with Haskell that jumped right out. One of the cases where Javascript takes the sort of easy path without thinking about the implications for the logic of the language as a whole
Denis Stoyanov
@xgrommx
Mar 09 2017 22:15
@dtipson this isn't good
Drew
@dtipson
Mar 09 2017 22:16
[1,2,3].reduceRight((acc,x)=>acc.concat(String(x)),'x') vs [1,2,3].reduce((acc,x)=>acc.concat(String(x)),'x')
Denis Stoyanov
@xgrommx
Mar 09 2017 22:17
and?
Robert Mennell
@skatcat31
Mar 09 2017 22:17
@ram-bot [1,2,3].reduceRight((acc,x)=>acc.concat(String(x)),'x')
ram-bot
@ram-bot
Mar 09 2017 22:17
'x321'
Robert Mennell
@skatcat31
Mar 09 2017 22:17
@ram-bot [1,2,3].reduce((acc,x)=>acc.concat(String(x)),'x')
ram-bot
@ram-bot
Mar 09 2017 22:17
'x123'
Nate Shoemaker
@nshoes
Mar 09 2017 22:18
@skatcat31 cool, thanks. that makes sense.
Robert Mennell
@skatcat31
Mar 09 2017 22:18
@nshoes http://semver.org/ more on semver
Denis Stoyanov
@xgrommx
Mar 09 2017 22:19
foldr(flip (++) . show) "x" [1,2,3] => x321
Robert Mennell
@skatcat31
Mar 09 2017 22:23
@xgrommx for those of us new to Haskell I'm guessing this shows that reduceRight is in fact behaving correctly?
Denis Stoyanov
@xgrommx
Mar 09 2017 22:25
@skatcat31 no
@skatcat31 :point_up: March 8, 2017 9:12 PM
Johnny Hauser
@m59peacemaker
Mar 09 2017 22:33
Is this good?
R.converge(R.assoc('toHere'), [
  R.pipe(R.path(['bar', 'fromHere']), R.pick(['a', 'b'])),
  R.identity
])({
  foo: {a: 123},
  bar: {
    fromHere: {a: 'a', b: 'b', c: 'c'}
  }
})
The need for R.identity makes me think I am overcomplicating it.
Robert Mennell
@skatcat31
Mar 09 2017 22:34
@xgrommx Okay so it's showing it is not working correctly then
Stefano Vozza
@svozza
Mar 09 2017 23:27
to remove a selection of keys from an object, there's R.omit
Piet Vandeput
@piet-v
Mar 09 2017 23:40
hi all, trying to make a kebab-case to Spaced Camel Case converter, is there anything I could improve?
const capitalizeHead = juxt([pipe(head, toUpper), tail]);
const kebabToCamelCase = pipe(
  split('-'),
  map(pipe(capitalizeHead, join(''))),
  join(' ')
);