These are chat archives for ramda/ramda

21st
Mar 2017
Vijay
@vijaytv
Mar 21 2017 00:52
@miwillhite , thanks. It looks like this problem is generating a lot of interest.
@skatcat31 , if we have a number like 20, I get [2,0] instead of 20
Vijay
@vijaytv
Mar 21 2017 00:59
@miwillhite , if my array starts with a 0, I get an empty array as the first element.
Vijay
@vijaytv
Mar 21 2017 01:09
@gmunguia , thanks. If the first item is 0, it returns an empty array as first element in the array though.
Johnny Hauser
@m59peacemaker
Mar 21 2017 01:35
I'm trying to compose Ramda functions to create mergeAllWith. I'd think I have to use reduce, but I can't see how that's possible.
I need to merge an array of objects
oh duh
I think I got it
I forgot the {} initial value to reduce haha
dumb brain
Josep M Sobrepere
@josepot
Mar 21 2017 02:19
mergeAllWith? I'm intrigued @m59peacemaker , would that work something like this?
mergeAllWith(
  sum,
  [
    { a: 'test', value: 1 },
    { b: 'test', value: 2 },
    { c: 'test', value: 3 },
    { d: 'test', value: 4 },
  ]
);

//=> { a: 'test', b: 'test', c: 'test', d: 'test', value: 10 }
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:20
yup
Josep M Sobrepere
@josepot
Mar 21 2017 02:20
interesting
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:20
reduce(mergeWith(add)) for example
Josep M Sobrepere
@josepot
Mar 21 2017 02:20
send a PR once you have the implementation. I've had use cases for that.
right
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:21
That's it :)
crud, I did it again!!
I am the worst goof
reduce(mergeWith(add), {})
more generalized, I think it's:
var mergeAllWith = curry2((fn, array) => reduce(mergeWith(fn), {})(array)
Josep M Sobrepere
@josepot
Mar 21 2017 02:26
mmmm.... not quite... because what if fn is something like mean or median?
do you know what I mean? :wink:
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:27
I don't :)
oh
Because it takes a single argument
Josep M Sobrepere
@josepot
Mar 21 2017 02:28
correct, you are accumulating, but what if the function that I want to apply can't be accumulative?
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:28
you don't want reduce then
Josep M Sobrepere
@josepot
Mar 21 2017 02:28
exactly
that's why for a more generalized way of doing reduce won't cut it.
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:28
It might actually be a good idea to do the thing I need to do and just failed at
I'm trying to do this fp style
var x = [
  {a: 1},
  {a: 2, b: 1},
  {a: 3, b: [1, 2]}
]
// => { a: [1, 2, 3], b: [1, [1, 2]] }
pipe(
  map(map(of)),
  reduce(mergeWith(concat), {})
)(x)
map(map(of)) FTW man I love fp
Josep M Sobrepere
@josepot
Mar 21 2017 02:33
:joy:
That's cool!
Denis Stoyanov
@xgrommx
Mar 21 2017 02:34
@m59peacemaker reduce(mergeWith((x, y) => [].concat(x, [y])), {})
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:36
mine is point-free-er, but yours is probably a lot less resource hungry
I can't use Ramda for this, so only needing mergeWith is good :)
lodash is unreal man
It has individual modules on npm, in this case, lodash.mergewith
somehow, that package alone bundles to be 4x larger than my whole project I want to use it in.
Josep M Sobrepere
@josepot
Mar 21 2017 02:42
@m59peacemaker are you aware of this: https://www.npmjs.com/package/babel-plugin-ramda ?
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:42
yeah, but I'm kinda not digging basically the whole Ramda thing no matter what
Ramda functions are amazing
but, the repo is not so good
The problem is, I have a package that adds less than 1kb to your project if you require('the-package'), but you can and probably will just require('the-package/one-function') and it's like a quarter of a kb.
So, adding Ramda as a dependency is just not cool
I can't justify the additional download time
Josep M Sobrepere
@josepot
Mar 21 2017 02:46
is this for a front-end or for a back-end project?
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:47
In other words, it's not just about the bundled size, it's also about the actual size of the package + it's dependencies, namely because this kind of junk is how you end up with so many MB of deps.
Either
Josep M Sobrepere
@josepot
Mar 21 2017 02:47
I get it
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:47
I won't touch Lodash ever for that reason, and I avoid any package that uses it
It's 5MB!
and people include it in a 1kb package just for one function!
I once had a project that was 50mb, 45mb of Lodash
Josep M Sobrepere
@josepot
Mar 21 2017 02:49
how did you package it? no tree-shaking, right?
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:50
I don't mean bundled
Josep M Sobrepere
@josepot
Mar 21 2017 02:50
ok ok
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:50
I mean like du -sh ./
Josep M Sobrepere
@josepot
Mar 21 2017 02:50
yep, yep
Johnny Hauser
@m59peacemaker
Mar 21 2017 02:51
What really pushed me over the edge is this happened right when yarn became available and that project and yarn didn't get along, so it was reinstalling all of it often
Josep M Sobrepere
@josepot
Mar 21 2017 02:52
yarn has improved a lot though since its initial release... But yep, I remember reading some pretty bizarre issues with lodash.
I've never used lodash, so...
well, just once, but that was a while ago
Johnny Hauser
@m59peacemaker
Mar 21 2017 03:41
What does this mean?
map > Also treats functions as functors and will compose them together.
Denis Stoyanov
@xgrommx
Mar 21 2017 03:42
@m59peacemaker map for function is compose
Johnny Hauser
@m59peacemaker
Mar 21 2017 03:45
ah!
map(append(2), of)(1) // => [1, 2]
Bravi
@Bravilogy
Mar 21 2017 11:51
James Forbes
@JAForbes
Mar 21 2017 12:26
Thank you very much @Bravilogy :)
Bravi
@Bravilogy
Mar 21 2017 12:39
@JAForbes is there a way to refactor lift(lift(fn))?
I was looking at liftN, but I guess it's just lift but with manual arity specification
James Forbes
@JAForbes
Mar 21 2017 12:44

@Bravilogy Good question. Not sure. But you could at least define lift lift separately, if you want to reuse it. I think it reads fine inline, particularly if you are only doing it once.

const liftTwice = compose(lift, lift)

const liftedTwice = liftTwice(fn)

You could also map and then run the lifted function in that inner context.

Lately I've found myself using R.sequence instead of lift, particularly with streams.

Bravi
@Bravilogy
Mar 21 2017 12:58
@JAForbes thanks, I'll have a look at that one now :)
Bravi
@Bravilogy
Mar 21 2017 14:20

Ok so I wanted to practice a bit with lift and here's a bit complex problem I came up with and its solution.

Scenario:
I'd like to fetch a user with an ID. Then I want to fetch all posts for that user and then I want to fetch all comments for each post. The end result should give me a nested and constructed object that looks something like this:

{
  //...userInfo,
  posts: [{
     //  ... an array of posts and for each post:
     comments: [ /* an array of comments */ ]
  }]
}
I used these endpoints:
http://jsonplaceholder.typicode.com/users/${id}
http://jsonplaceholder.typicode.com/posts?userId=${userId}
http://jsonplaceholder.typicode.com/comments?postId=${postId}
and finally, here's the code:
const httpGet = url =>
    new Task((reject, resolve) =>
        fetch(url)
        .then(res => res.json().then(resolve))
        .catch(reject));

const getUser = id =>
    httpGet(`http://jsonplaceholder.typicode.com/users/${id}`);

const getPosts = userId =>
    httpGet(`http://jsonplaceholder.typicode.com/posts?userId=${userId}`);

const getComments = postId =>
    httpGet(`http://jsonplaceholder.typicode.com/comments?postId=${postId}`);

const withComments = traverse(Task.of, converge(lift(merge), [
    Task.of,
    compose(
        lift(compose(objOf('comments'), map(dissoc('postId')))),
        getComments,
        prop('id')
    )
]));

const withPosts = useWith(merge, [
    identity,
    compose(objOf('posts'), map(dissoc('userId')))
]);

const getUserPosts = id =>
    Task.of(withPosts)
        .ap(getUser(id))
        .ap(chain(withComments, getPosts(id)));

getUserPosts(1).fork(console.error, console.log);
Bravi
@Bravilogy
Mar 21 2017 14:26
with dot chaining it was a bit less code
so perhaps this could've been done better :D but oh well..
Alex Deas
@alex-deas
Mar 21 2017 15:13
@ram-bot
propOr('', 'a')({
  a: undefined
});
ram-bot
@ram-bot
Mar 21 2017 15:13
undefined
Alex Deas
@alex-deas
Mar 21 2017 15:13
@ram-bot
pathOr('', ['a'])({
  a: undefined
});
ram-bot
@ram-bot
Mar 21 2017 15:13
''
Bravi
@Bravilogy
Mar 21 2017 15:14
interesting :D
Alex Deas
@alex-deas
Mar 21 2017 15:14
Should those two not return the same values? Documentation says it will return the or for non-null. Not sure if undefined would be classes as non-null but they should be consistent
Johnny Hauser
@m59peacemaker
Mar 21 2017 15:18
[ [foo: 123], [bar: 'abc'], [baz: true] ] // => { foo: 123, bar: 'abc', baz: true }
any idea what to call this?
that could be made something zippable...
oops, bad syntax
[ ['foo', 123], ['bar', 'abc'], ['baz', true] ] // => [ [ 'foo', 'bar', 'baz' ], [ 123, 'abc', true ] ]
@m59peacemaker transpose([ ['foo', 123], ['bar', 'abc'], ['baz', true] ] )
@ram-bot
transpose([ ['foo', 123], ['bar', 'abc'], ['baz', true] ] )
ram-bot
@ram-bot
Mar 21 2017 15:27
[ [ 'foo', 'bar', 'baz' ], [ 123, 'abc', true ] ]
Bravi
@Bravilogy
Mar 21 2017 15:32
@xgrommx would you be able to give me an example of what that function does?
Denis Stoyanov
@xgrommx
Mar 21 2017 15:41
@Bravilogy what do u want to use liftA2?
Just RAG
@justrag
Mar 21 2017 16:06
I need to "verify" a param: leave it as it is if it's of one of the legal values and change it to some default if it isn't. Is unless the best method for it?
Johnny Hauser
@m59peacemaker
Mar 21 2017 16:15
@xgrommx thanks!
Johnny Hauser
@m59peacemaker
Mar 21 2017 16:25

I have data that is like this:

[
  {key, value, collectionStrategy},
  {key, value, collectionStrategy},
  {key, value, collectionStrategy}
]

I need to merge all the objects into one, and the collectionStrategy has been applied to the values. What the strategy represents is how to deal with key conflicts (OR LACK OF KEY CONFLICT!)

The last part being the really dang hard part.
mergeWith will only deal with conflicts, but I need to also do something where there aren't conflicts
and also collectionStrategy has priority, two of the same keys might have different strategies, and one has to take precedence over the other
This is quite tough.
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:24
var data = [
  {k: 'greetings', v: 'hi',           s: 'alwaysArray'},
  {k: 'number',    v: 1,              s: 'arrayWhenMore'},
  {k: 'letters',   v: ['a', 'b'],     s: 'arrayWhenMore'},
  {k: 'greetings', v: ['hey', 'sup'], s: 'alwaysArray'},
  {k: 'greetings', v: 'yo',           s: 'arrayWhenMore'},
  {k: 'letters',   v: 'c',            s: 'arrayWhenMore'},
  {k: 'foo',       v: 'bar',          s: 'alwaysArray'}
]
someFn(
  [ {alwaysArray: identity}, {arrayWhenMore: (values, k) => values.length > 1 ? values : values[0]} ],
  data
)
/* => {
  greetings: [ 'hi', [ 'hey', 'sup' ], 'yo' ],
  number: 1,
  letters: [ [ 'a', 'b'], 'c' ],
  foo: [ 'bar' ]
}*/
Matthew Willhite
@miwillhite
Mar 21 2017 17:26
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:26
I don't think so
Matthew Willhite
@miwillhite
Mar 21 2017 17:27
Then use cond or something in the fn to check the s keys and apply the correct operation
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:27
Yeah, as I said above, though
you end up with all the keys that didn't conflict not having the strategy applied
in other words, some values should be arrays, but they didn't conflict with anything, so they are just single values
Matthew Willhite
@miwillhite
Mar 21 2017 17:28
ah…like foo would just be ”bar”, but you want it wrapped in an array
possibly compose(evolve({ /* ensure you ended up with the right type */ }), mergeWithKey(fn))
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:29
yeah, and at that point, any kind of marker you put into the data to identify that the strategy still needs to occur on an item, could have been put there by the function resolving the conflicts
but it's same problem again there!
Matthew Willhite
@miwillhite
Mar 21 2017 17:30
evolve({ foo: unless(isArrayLike, of) })
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:30
Then there can't be single values!
Matthew Willhite
@miwillhite
Mar 21 2017 17:30
so foo could be any type?
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:30
yep
including arrays
the thing to do here
collect all of it as arrays, then let the strategies take the collection and decide what to do
my someFn seems to be a good, if not the perfect API
but making it work is tough!
Matthew Willhite
@miwillhite
Mar 21 2017 17:31
Yeah, harder that you can’t make assumptions about the input data
there is no way you can know what you are getting?
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:32
nope
Matthew Willhite
@miwillhite
Mar 21 2017 17:32
haha fun
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:32
the only thing you can actually know is that there won't be any functions, but....
any solution that gets to that point is really going to be ugly
Matthew Willhite
@miwillhite
Mar 21 2017 17:32
yeah…just a lot of checks
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:32
I could use a function as a marker and know that it's a marker for this purpose
but come on
there's got to be a better way =D
Matthew Willhite
@miwillhite
Mar 21 2017 17:33
I’m curious what the usecase for this is…
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:33
It's terribly specific
I wrote a query string parser
there's this crazy edge case that I caught on test 163!
also bear in mind that you can encode an object as a JSON string and use it as a query string value, and my parser will see that and decode it for you
so, your values can be absolutely anything therefore
(except functions)
Matthew Willhite
@miwillhite
Mar 21 2017 17:34

for example…knowing the tiny bit I know I would lean towards this strategy:

Before you get to this function, break up your input into actual types using something like daggy.taggedSum.

Then define concat for the types (then you get .cata to handle the various cases) and just use mergeWith(concat, input) at this level

Meaning…shove it into a state you can deal with as early as possible
then everything else will be simpler
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:35
that made no sense to me! but hold on and I'll try to get it
So, there's also this thing with query strings where you can represent arrays like foo=a&foo=b&foo=c
Just RAG
@justrag
Mar 21 2017 17:35
Is a first normalizing pass not viable?
Matthew Willhite
@miwillhite
Mar 21 2017 17:36
@justrag That’s a good way to put it ;)
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:36
or foo[]=a&foo[]=b&foo[]=c
Just RAG
@justrag
Mar 21 2017 17:36
Treat everything that's not an array with an R.of
Matthew Willhite
@miwillhite
Mar 21 2017 17:36
right…so as early as possible…figure out what foo is
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:36
the thing that screwed my test is foo=a is a single value
foo[]=a is always an array
but wait
there could or could not be duplicates of either those
so, it's quite a tough thing
as I iterate, I know 3 things -> the key, the value, and whether it has to be an array or might not be
Matthew Willhite
@miwillhite
Mar 21 2017 17:38

You want to get to a point where you have a definition for every kind of data that you’ve parsed out.
And each one of those definitions has a single API for merging. Probably concat (I think, still new to this).

So that it doesn’t matter if foo is an array, a number, or a string. You call concat(x, y) on it and it’ll do what you need.

Just RAG
@justrag
Mar 21 2017 17:39
If the key can repeat, maybe you can use an array of single-key objects?
Matthew Willhite
@miwillhite
Mar 21 2017 17:39
somebody correct me if I’m wrong, but I think you want to handle the typing as soon as possible (like immediately when you are parsing the string), so that any sort of combining, mapping etc follows a really simple api
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:39
I'm not following you guys :/
but for starters, my API above was def. wrong then?
Just RAG
@justrag
Mar 21 2017 17:40
[{key1: 'val1'},{key2: 'val2'},{key1:'oh, you again'}]
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:40
but... that's what I have already..
except it's missing critical info
Just RAG
@justrag
Mar 21 2017 17:41
Yeah, and you need to parse it into something more regular as soon as possible :)
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:41
There's no way to know if the result should be {key2: 'val2'} or {key2: ['val2']}
Just RAG
@justrag
Mar 21 2017 17:41
Then put it always into {key2: ['val2']}
Even if there's only one, create an array.
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:42
then how would I know if it's actually an array or a single value?
Just RAG
@justrag
Mar 21 2017 17:42
.length?
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:42
then there's no way to know the result actually ought to have been {key2: 'val2'}
I'm afraid you're not grasping the issue.
Just RAG
@justrag
Mar 21 2017 17:42
Quite possible ;)
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:42
I know 3 things - key, value, and whether the result HAS to be an array or not
if not, then it can just be the value if there are not more of them
Just RAG
@justrag
Mar 21 2017 17:43
Oh, then you need another field.
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:43
If so, the value has to be an array even if there are not more of them
My data above has 3 fields :)
Just RAG
@justrag
Mar 21 2017 17:43
Like {key2: {isSingle: true, val: val2}}
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:43
But, shouldn't a proper abstraction not have to rely on these two specific use cases?
Just RAG
@justrag
Mar 21 2017 17:43
But it's not gonna be nice to parse.
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:45
I feel like it should be possible to merge a bunch of objects with each item specifying what it would prefer to do, and a list of priorities from which the top one is chosen when there is a conflict
{foo: wantsToBeArray}
{foo: wantsToBeSingleIfPossible}
Just RAG
@justrag
Mar 21 2017 17:46
You probably need to write a specific reduce function.
With a switch or something.
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:48
could the best solution involve me not thinking about how to compose a bunch of functions together, and be more in the realm of creating a custom type that implements concat and such?
is that what @miwillhite was getting at?
I've never done anything like that
Matthew Willhite
@miwillhite
Mar 21 2017 17:49
Well, I was trying to map it out…is this for processing one query string and building the data structure from that?
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:49
yeah
I can make the function I came up with above. It's still tough, but it will work
you just end up with strategy functions that take all the values and return the value for the key
What sucks about it is it depends on the structure of the data set
{k, v, strategy}
or whatever
Having a merge function that relies on objects having certain key names is a HUGE fail.
Bravi
@Bravilogy
Mar 21 2017 17:51
hey guys, I'm struggling with re-writing this ramda way
const fn = id => getUser(id)
    .chain(user => getPosts(user.id)
        .chain(traverse(Task.of, post => getComments(post.id)
            .map(comments => ({
                ...dissoc('userId', post),
                comments: comments.map(dissoc('postId'))
            }))
        ))
        .map(posts => ({ ...user, posts })));
Matthew Willhite
@miwillhite
Mar 21 2017 17:51
ok, so this is rough and not completely thought out, but maybe this will illustrate a little better what I was thinking:
┌──────────────┐                                     
│ QueryString  │                                     
└──────────────┘                                     

┌─────────────────────────────────┐                  
│                                 │                  
│QueryStringPart = { String       │                  
│                  , Number       │                  
│                  , Array        │                  
│                  , Object       │                  
│                  , Bool         │                  
│                  }              │                  
│                                 │                  
└─────────────────────────────────┘                  

┌─────────────────────────────────────────┐          
│QueryStringPart.prototype.concat = b => {│          
│  return this.cata({                     │          
│    String: <your merge strategy>        │          
│    Number: <your merge strategy>        │          
│    Array:  <your merge strategy>        │          
│    ...                                  │          
│}                                        │          
│                                         │          
└─────────────────────────────────────────┘          

┌───────────────────────────────────────────────────┐
│                                                   │
│                                                   │
│reduce(                                            │
│ (acc, o) => mergeWith(concat, acc, o),            │
│ {},                                               │
│ queryStringParts                                  │
│)                                                  │
│                                                   │
│                                                   │
│                                                   │
└───────────────────────────────────────────────────┘
You first generate all your parts, just a list…taking it a value at a time
you have some typing function at that level to make sure you put it into the right part
each part has it’s own merge strategy
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:52
I don't think that's the right thing there
Matthew Willhite
@miwillhite
Mar 21 2017 17:52
then when you want to put together the final structure, you just fold it down
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:52
I don't see a reason for each type to have a strategy
Robert Mennell
@skatcat31
Mar 21 2017 17:53
@m59peacemaker what database are you using?
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:53
none
The strategy is based on the key having [] or not
If it has brackets, then the value has to be an array, whether there are more of it or not
Matthew Willhite
@miwillhite
Mar 21 2017 17:53
you know what keys you are going to have but you don’t know what type they are going to be?
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:53
nope
Matthew Willhite
@miwillhite
Mar 21 2017 17:53
then force everything to be an array
?
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:53
then you can't NOT have an array :)
haha
man this is fun
Matthew Willhite
@miwillhite
Mar 21 2017 17:54
what is the rule for NOT making it an array?
if it just has one element?
Johnny Hauser
@m59peacemaker
Mar 21 2017 17:54
foo=a and no more of them
foo=a&foo=b definitely an array
foo[]=a and no more of them - always an array
and remember, the obvious trick of concating to previous arrays won't work, since a can actually be an array
then you end up concating to a thing that itself should be a value
so again, the easy thing to do is just collect them all first, along with markers for keys that had brackets (or just keep the brackets)
but, keeping the brackets isn't helpful, because non-bracketed equivalents count just the same
in edge case that some dummy does foo[]=a&foo=b
and there's also two kinds foo[]=a&foo[1]=b
so, best to just strip them off and note that this value must be an array inevitably
and therefore, the easiest starting place is to collect everything in arrays, and have markers for the items that have to stay that way
the items that don't, you can value[0] it if length = 1
I can make this "work". That's not so bad. But doing it well is another matter.
Matthew Willhite
@miwillhite
Mar 21 2017 17:59
if everything is an array…(even when you just want the value) then you can still just use map to get the value out
result.number.map(/ here is your value /)
haha idk…gotta run though
it sounds like a fun problem
Johnny Hauser
@m59peacemaker
Mar 21 2017 18:00
peace
Matthew Willhite
@miwillhite
Mar 21 2017 18:00
good luck, be sure to share
Johnny Hauser
@m59peacemaker
Mar 21 2017 18:00
I'll finish the crappy solution and share it in a few yeah
Matthew Willhite
@miwillhite
Mar 21 2017 18:00
lolol
Robert Mennell
@skatcat31
Mar 21 2017 18:05
Too bad you don't get to enforce that array values appear inside JSON on your querystring parser... f=[a,b,c]
Johnny Hauser
@m59peacemaker
Mar 21 2017 18:05
I do rather like encoding all nesting as JSON, but it is by far not the norm
foo=a&foo=b I think is the most common
btw, funny thing, the wildly popular query-string has the issue I am fixing in my own
parse('foo[]=a') // => { foo: 'a' }
qs does it correctly
parse('foo[]=a') // => { foo: ['a' ]}
I'm not happy with either of them, though.
Johnny Hauser
@m59peacemaker
Mar 21 2017 18:20
is there a thing to do instead of map(map(
?
Bravi
@Bravilogy
Mar 21 2017 23:20
can I make these point free somehow?
const fn = (id, data) => find(propEq('id', id), data);
const fnn = (id, data) => findIndex(propEq('id', id), data);

const findBoth = converge(Pair, [fn, fnn]);
Piet Vandeput
@piet-v
Mar 21 2017 23:21
usewith?
Bravi
@Bravilogy
Mar 21 2017 23:21
const fn = useWith(find, [propEq('id'), identity]);
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:21
@miwillhite I'm nowhere close to a clue what to name this, bu here is the least bad version I've done
var data = [
  {key: 'greetings', value: 'hi', meta: {array: true}},
  {key: 'number',    value: 1},
  {key: 'letters',   value: ['a', 'b']},
  {key: 'greetings', value: ['hey', 'sup'], meta: {array: true}},
  {key: 'greetings', value: 'yo'},
  {key: 'letters',   value: 'c'},
  {key: 'foo',       value: 'bar', meta: {array: true}},
  {key: 'bar',       value: [123]}
]
var result =   {
  greetings: [ 'hi', [ 'hey', 'sup' ], 'yo' ],
  number: 1,
  letters: [ [ 'a', 'b'], 'c' ],
  foo: [ 'bar' ],
  bar: [123]
} 
var mergeAllWith = curry((fn, objects) => reduce(mergeWith(fn), {})(objects))

var wowCode = pipe(
  groupBy(prop('key')),
  map(pipe(
    map(map(of)), // everything to arrays to prep for concat
    mergeAllWith(concat), // all values in one array
    ({value, meta}) => {
      if (value.length > 1 || contains({array: true}, meta || [])) { return value }
      return value[0]
    }
  ))
)
equals(wowCode(data), result) // => true at last, true at last, thank God, true at last!
Bravi
@Bravilogy
Mar 21 2017 23:21
yeah that would work hmm
Piet Vandeput
@piet-v
Mar 21 2017 23:21
:)
Bravi
@Bravilogy
Mar 21 2017 23:22
thanks :D
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:22
I can't believe what is now those few lines of code has been the most difficult problem for me to solve thus far in my life.
or rather, doing it in a not utterly nasty way.
Piet Vandeput
@piet-v
Mar 21 2017 23:26
not sure, but isn't that map(pipe( unnecessary? as in: doesn't map compose functions?
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:26
mm....
Piet Vandeput
@piet-v
Mar 21 2017 23:26
so could it just be replaced with map(
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:26
but then wouldn't I just do map(map ?
Piet Vandeput
@piet-v
Mar 21 2017 23:27
I mean, isn't pipe concatting those 3 functions
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:27
I am composing a pipeline of functions and passing it to map
Piet Vandeput
@piet-v
Mar 21 2017 23:27
ye
if u pass 3 functions to map
without pipe
it'll compose too
map = compose for functions?
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:27
but then I'm not mapping over my data
Piet Vandeput
@piet-v
Mar 21 2017 23:28
sec, I gnna REPL this x)
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:28
and data at the end still?
I think I get it. Just a little magical.
well, removing the pipe threw an error for me
Piet Vandeput
@piet-v
Mar 21 2017 23:29
ye seems so :O
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:30
oh yeah, also
map(...fns) is compose, not pipe
that may be the issue
flip(map) didn't fix it either, though
Piet Vandeput
@piet-v
Mar 21 2017 23:31
yes
it's compose, but dunno, it's a stab in the dark xD
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:32
oh yeah, I remember now
you can only do 2 fns
Bravi
@Bravilogy
Mar 21 2017 23:33
is it possible to push an item in array to a specific index?
actually to append an array
Johnny Hauser
@m59peacemaker
Mar 21 2017 23:33
var compose = reduce(map, identity) maybe?
Bravi
@Bravilogy
Mar 21 2017 23:33
at a specific index
Piet Vandeput
@piet-v
Mar 21 2017 23:34
so basically move it to back of the array?
Bravi
@Bravilogy
Mar 21 2017 23:35
no, let's say I have an object and want it to be 3rd index
I'm basically trying to create drag and drop
I've got the dragged item index and drop area item index
and I'm trying to figure out how to actually push the item in there :D
Piet Vandeput
@piet-v
Mar 21 2017 23:36
something with R.insert I guess
Bravi
@Bravilogy
Mar 21 2017 23:37
No lists have been harmed in the application of this function.
lol
nice!