These are chat archives for ramda/ramda

5th
Apr 2017
Johnny Hauser
@m59peacemaker
Apr 05 2017 00:08
yup. That's not good.
Gabe Johnson
@gabejohnson
Apr 05 2017 00:14
@JAForbes Makes sense about the dependency. I'll be keeping tabs.
I really like the union-type API. It's higher level than sanctuary-def. Have you talked to David about where he's going w/ that project?
James Forbes
@JAForbes
Apr 05 2017 01:19

David and me have talked a fair bit about it. It was even going to be a part of the sanctuary organization, but we decided to rain check that because the api for sum-type didn't fit into the sanctuary "style".

I think sum-type will probably stay in its own namespace, but sanctuary-def may one day have its own notion of enumerated types, and sum-type will probably eventually be a higher level thin opinionated api layer that sits on top of that.

It will still be very much like the union-type api, just with less stuff. In practice I've found those extra features are less useful than they initially appear, or they're useful but the current interface leads to either error prone or brittle caller code.

I've gone and ranted on the topic in some of the issues there, feel free to rebuke it there if you disagree, or have questions, I won't release 1.0 for months yet, I'm going to live with it in a work project and iterate on the interface a lot before publishing it on npm
Gabe Johnson
@gabejohnson
Apr 05 2017 01:36
Dogfooding is a great way to test ideas. I look forward to seeing where you go with it.
Matthew Willhite
@miwillhite
Apr 05 2017 02:09
@JAForbes thanks for the feedback on streams
Brian McKenna
@puffnfresh
Apr 05 2017 06:02
that looks good
James Forbes
@JAForbes
Apr 05 2017 08:10
@miwillhite :)
Stephan Meijer
@smeijer
Apr 05 2017 08:21
const list = {
  tasks: [
    { id: 2, state: 'todo', users: [{ id: 'u1' }] },
    { id: 3, state: 'todo', users: [{ id: 'u1' }, { id: 'u3' }] },
    { id: 4, state: 'todo', users: [{ id: 'u2' }] },
  ],
};

const getUserIds = R.compose(
  R.uniq,
  R.pluck('id'),
  R.flatten,
  R.pluck('users'),
  R.propOr([], 'tasks'),
);

const userIds = getUserIds(list);
I want to have the unique userIds from the tasks. This is what I came up with. Does one of you have a nicer solution, or is this pretty enough?
I can't get my head around lenses, but feel like they should come usefull here.
Rodrigo Álvarez
@Papipo
Apr 05 2017 09:43
Hi!
Denis Stoyanov
@xgrommx
Apr 05 2017 09:43
hi!
Rodrigo Álvarez
@Papipo
Apr 05 2017 09:44
How can I do something like ifElse to check if any arguments have been provided? I want to implement a getter-setter function
thus, this function would call get if args.length==0 or set (with the first arg) if args.length!= 0
Denis Stoyanov
@xgrommx
Apr 05 2017 09:45
@Papipo try cond or compose(ifElse, unapply(identity))
unapply(identity) transform arguments to list
Rodrigo Álvarez
@Papipo
Apr 05 2017 09:46
I'll check that out, thanks
Rodrigo Álvarez
@Papipo
Apr 05 2017 10:02
Can I shorten this with flip?
const get = lens => R.view(lens, state)
making it a pointfree function
Raine Virta
@raine
Apr 05 2017 10:04
did you try
Rodrigo Álvarez
@Papipo
Apr 05 2017 10:05
I'll try in a moment
I don't know why I even asked XD
Denis Stoyanov
@xgrommx
Apr 05 2017 10:05
@Papipo view curried
@Papipo flip(view)(state)
Stefano Vozza
@svozza
Apr 05 2017 10:27
const get = R.view(R.__, state)
Raine Virta
@raine
Apr 05 2017 12:27
not sure that's a good name since it seems like people sometimes type ramda as rambda by mistake
Rodrigo Álvarez
@Papipo
Apr 05 2017 12:28
In fact I did that several times when I wanted to learn how to use ramda
Denis Stoyanov
@xgrommx
Apr 05 2017 12:33
@raine I don't like this library :smile:
Rick Medina
@rickmed
Apr 05 2017 12:46
terrible name :) @xgrommx you mean rambda right? why not?
Denis Stoyanov
@xgrommx
Apr 05 2017 12:46
@rickmed yes, I don't like rambda
Rick Medina
@rickmed
Apr 05 2017 12:48
got it
Denis Stoyanov
@xgrommx
Apr 05 2017 12:49
I also have some ideas, how we can rewrite Ramda with built-in methods in js
but I don't publish or create library for this one
for example evolve
const evolve__ = transformObj => obj => {
  return Reflect.ownKeys(obj).reduce((acc, key) => {    
    return Object.assign({}, acc, {
      [key]: transformObj[key] ? 
      (typeof transformObj[key] === 'function' 
       ? transformObj[key](obj[key]) : evolve__(transformObj[key])(obj[key])) : obj[key]
    })
  }, {});
}
or applySpec
const applySpec__ = transformObj => (...args) => {
  return Reflect.ownKeys(transformObj).reduce((acc, key) => {
    return Object.assign({}, acc, {
      [key]: typeof transformObj[key] === 'function' ? 
      transformObj[key](...args) : 
      applySpec__(transformObj[key])(...args)
    })
  }, {});
};
Rick Medina
@rickmed
Apr 05 2017 12:54
the argument there would be browser support, but I get the point
Martin Broder
@mrtnbroder
Apr 05 2017 12:56
Hey folks!
Drew
@dtipson
Apr 05 2017 12:56
Why Reflect.ownKeys? Doesn't that return nonenumerable things like [Symbol.iterator]?
Martin Broder
@mrtnbroder
Apr 05 2017 12:56
I wanna put this little helper function here on the cookbook page of ramda
but there is already a function called 'traverse' on the ramda lib
so I was wondering if you have any other ideas for this beauty here:
// traverseArray = <T> (fn: (a: T => T)) => <T> (a: Array<T>): Array<T>
const traverseArray = (fn, a) => R.map(traverse(fn), a)

// traverseObject = <T> (fn: (a: T => T)) => <T> (a: any): T
const traverseObject = (fn, a) => {
  const keys = Object.keys(a)

  return keys.reduce((obj, key) => {
    return fn({
      ...obj,
      [key]: traverse(fn)(obj[key]),
    })
  }, a)
}

//
// Recursively applys a function on each entity of a Tranversable
//
// traverse = <T> (fn: (a: T => T)) => <T> (a: T): T
export const traverse = (fn) => (a) => {
  if (Array.isArray(a)) {
    return traverseArray(fn, a)
  } else if (typeof a === 'object' && a !== null) {
    return traverseObject(fn, a)
  }

  return a
}
Denis Stoyanov
@xgrommx
Apr 05 2017 12:59
@mrtnbroder my old material :smile: https://jsbin.com/lonexec/7/edit?html,js,output
Martin Broder
@mrtnbroder
Apr 05 2017 13:03
looks neat but mutates the native Object :P
Denis Stoyanov
@xgrommx
Apr 05 2017 13:06
@mrtnbroder here?
const traverseObj = (of, f) => o => {
  const keys = Reflect.ownKeys(o);
  return traverse(of, f, keys.map(k => o[k])).map(zipObj(keys));
};
Martin Broder
@mrtnbroder
Apr 05 2017 13:11
not that one
Martin Broder
@mrtnbroder
Apr 05 2017 13:34
but it's kinda different to my version
Raine Virta
@raine
Apr 05 2017 13:56
@ram-bot
js
ram-bot
@ram-bot
Apr 05 2017 13:56
undefined
Raine Virta
@raine
Apr 05 2017 13:57
@ram-bot
fn1 = x => concat(toUpper(x), reverse(x))
fn2 = lift(concat)(toUpper, reverse)
fn3 = ap(map(concat, toUpper), reverse)
fn4 = converge(concat, [toUpper, reverse])

ap([fn1, fn2, fn3, fn4], ['foo'])
ram-bot
@ram-bot
Apr 05 2017 13:57
[ 'FOOoof', 'FOOoof', 'FOOoof', 'FOOoof' ]
Galileo Sanchez
@galileopy
Apr 05 2017 14:07
do someone know another way to do this? const authorDate = ([author, date]) => ({author, date });
James Forbes
@JAForbes
Apr 05 2017 14:08
const authorDate = zipObj(['author', 'date']) works
Galileo Sanchez
@galileopy
Apr 05 2017 14:08
thanks @JAForbes
James Forbes
@JAForbes
Apr 05 2017 14:09
my pleasure
you might want unapply to if you want it to be a spread
like a lot of constructors for example
e.g.
const authorDate = unapply(zipObj(['author', 'date']))

authorDate('hi', 'there')
Galileo Sanchez
@galileopy
Apr 05 2017 14:12
@JAForbes that's cool, I get a pair already so the vanilla version it's ok
can I use a lens to perform transformations? eg {author: [X], date: [Y], another: Z} -> {list: zip([X],[Y]), another: Z}
right now I'm doing
    converge(
        useWith(merge, [objOf("string"), objOf("list")]),
        [
            prop("string"),
            converge(zip, [prop("author"), prop("date")])
        ]
    ),
Martin Broder
@mrtnbroder
Apr 05 2017 14:21
This message was deleted
Galileo Sanchez
@galileopy
Apr 05 2017 14:35
how could I make something like and(firstIsA, secondIsB) (A, B) === true
how could I call a function that behaves like the one mentioned above?
Galileo Sanchez
@galileopy
Apr 05 2017 14:50
how do I make somethin like anyPass but where each predicate receives 2 arguments?
it is to use with groupWith
Raine Virta
@raine
Apr 05 2017 14:55
all predicate functions receive the same arguments?
Galileo Sanchez
@galileopy
Apr 05 2017 15:00
yes they all receive a string
Raine Virta
@raine
Apr 05 2017 15:01
String -> String -> Boolean?
Galileo Sanchez
@galileopy
Apr 05 2017 15:03
ended up doing as follows
    groupWith(
        pipe(
            pair,
            anyPass([
                apply(useWith(and, [test(/^Commit:/), test(/^CommitDate:/), ])),
                apply(useWith(and, [test(/^Commit:/), test(/^    /)])),
                apply(useWith(and, [test(/^    /), test(/^    /)])),
            ])
        )
    )
pair then apply so anyPass doesn't mess with binarity of my functions
Raine Virta
@raine
Apr 05 2017 15:08
it does look like there might be a pattern to be pulled into a separate function
predicate list can be map(apply)'ied instead if you prefer
Galileo Sanchez
@galileopy
Apr 05 2017 15:10
it does, I just don't know what to call it
you say anyPass(map(apply, predicatelist))
is there a way to transform [a, b, ...c] to {first: a, second: b, rest: c}
Raine Virta
@raine
Apr 05 2017 15:17
basically what you said
@ram-bot
fn = ([a, b, ...c]) => ({ first: a, second: b, rest: c })
fn([1, 2, 3, 4])
ram-bot
@ram-bot
Apr 05 2017 15:18
{ first: 1, second: 2, rest: [ 3, 4 ] }
Galileo Sanchez
@galileopy
Apr 05 2017 15:58
@raine ended up using lenses, and saw that this was perfectly clear and went with your approach
Bravi
@Bravilogy
Apr 05 2017 20:23
hello
I have an array of objects and I'm trying to find an object by specific property and then update one of its properties and return the updated array
should I use lens for this or is there a simpler solution?
Is this a single object in the array, or could it be multiple?
Bravi
@Bravilogy
Apr 05 2017 20:28
multiple
I'll post my version in a second
Bravi
@Bravilogy
Apr 05 2017 20:38
ok a bit of refactor
https://goo.gl/cWBMRR
Brad Compton (he/him)
@Bradcomp
Apr 05 2017 20:46
@Bravilogy I use map(when(...)) for that sort of thing: https://goo.gl/TTSkLY
Robert Mennell
@skatcat31
Apr 05 2017 20:50
@Bradcomp darnit.. was really close to your example but I attempted to use a set with lense...
didn't work. Any idea why?
Bravi
@Bravilogy
Apr 05 2017 20:51
damn :D that's so simple
I was going towards the lenses too
I was working on another solution now using converge within useWith
with lenses
and my brain was melting
apparently set wasn't as simple as I thought it would be in this case XD
Bravi
@Bravilogy
Apr 05 2017 20:54
you need to use over
instead of set
set just sets a property doesn't it? whatever you pass as a second argument, in this case a function
Robert Mennell
@skatcat31
Apr 05 2017 20:56
// set code
module.exports = _curry3(function set(lens, v, x) {
  return over(lens, always(v), x);
});
so that answers why it didn't work like I thought it would
@Bravilogy yeah... confused set and over for a bit...
Brad Compton (he/him)
@Bradcomp
Apr 05 2017 21:04
@Bravilogy I think you could still use the lens instead of evolve. Of course you could also generalize it to an updateWhere function with the predicate and mapping function as parameters.
generalized so binding can happen
Kurt Milam
@kurtmilam
Apr 05 2017 23:44
I have a function curried like this: add = x => y => x + y. Is there something like apply that would allow me to call the function like somethingLikeApply( add, [ 1, 2 ] ) ?
Raine Virta
@raine
Apr 05 2017 23:49
not exactly what you're looking for but
@ram-bot
add = x => y => x + y
apply(uncurryN(2, add), [1, 2])
ram-bot
@ram-bot
Apr 05 2017 23:49
3
Kurt Milam
@kurtmilam
Apr 05 2017 23:52
This also seems to work:
reduce( call, add )( [ 1, 2 ] )
@ram-bot
reduce( call, add )( [ 1, 2 ] )
ram-bot
@ram-bot
Apr 05 2017 23:53
3
Kurt Milam
@kurtmilam
Apr 05 2017 23:54
I'd be surprised if there wasn't a name for reduce( call )