These are chat archives for ramda/ramda

29th
Mar 2016
Jason Kurian
@JaKXz
Mar 29 2016 07:28

could someone help me understand the placeholder better? I tried:

const findById = R.find(R.propEq('id', R._));

but got errors when I tried to do something like:

findById(b.resource_id)(resources)
                                 ^

TypeError: findById(...) is not a function
Raine Virta
@raine
Mar 29 2016 07:31
R.useWith(R.find, [ R.propEq('id'), R.identity ]);
Jason Kurian
@JaKXz
Mar 29 2016 07:36

nice! I ended up going with

const findById = (id) => R.find(R.propEq('id', id));

since it reads a little better

but i’ll look into useWith
Raine Virta
@raine
Mar 29 2016 07:37
that can't be called as `findById('someid', data);
you'd need curry((id, arr) => R.find(R.propEq('id', id), arr))
kwijibo @kwijibo still reading promises-aplus/promises-spec#94
Scott Christopher
@scott-christopher
Mar 29 2016 09:23
Sorry @JAForbes, I didn't get back to my desk all day. One of those days.
James Forbes
@JAForbes
Mar 29 2016 09:24
no problem, and no rush :)
Scott Christopher
@scott-christopher
Mar 29 2016 09:25
Anyway, here's one example of defining a reducing function recursively...
function reducePath(props, fn, init, list) {
  if (props.length === 0) {
    return res;
  } else if (props.length === 1) {
    return reduce((acc, x) => fn(acc, x[props[0]]), init, list);
  } else {
    return reducePath(tail(props), fn, init, chain(prop(props[0]), list));
  }
}
If your data follows the pattern of nested arrays of objects like your a, b, c example then this can be used like:
reducePath(['a', 'b', 'c'], flip(append), [], data)
e.g. if data is:
[
  { a: [{ b: [{ c: { id: 1 } }] },
        { b: [{ c: { id: 2 } },
              { c: { id: 3 } }] }] },
  { a: [{ b: [{ c: { id: 4 } }] },
        { b: [{ c: { id: 5 } },
              { c: { id: 6 } }] }] },
]
then the above call would result in:
[{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}]
If the data is a bit more unstructured, another approach would be to have the function take a predicate that it can use to test whether it has found its target...
function searchReduce(p, fn, init, obj) {
  if (p(obj)) {
    return fn(init, obj);
  } else {
    switch (type(obj)) {
      case 'Object':
        return reduce((acc, x) =>
          searchReduce(p, fn, acc, x), init, values(obj));
      case 'Array':
        return reduce((acc, x) =>
          searchReduce(p, fn, acc, x), init, obj);
      default:
        return init;
    }
  }
}
and
searchReduce(has('id'), (acc, obj) => append(obj.id, acc), [], data)
results in
[1, 2, 3, 4, 5, 6]
James Forbes
@JAForbes
Mar 29 2016 09:30
that searchReduce is great!, ... is it possible to break when a predicate is met, or make it a transducer or something?
Scott Christopher
@scott-christopher
Mar 29 2016 09:32
my experience with transducers is pretty limited, so I couldn't say for certain
James Forbes
@JAForbes
Mar 29 2016 09:32
thank you for these examples, give me something to ruminate on
Scott Christopher
@scott-christopher
Mar 29 2016 09:32
you might be able to use R.reduced to short circuit the reduce
James Forbes
@JAForbes
Mar 29 2016 09:33
yeah I am mainly thinking about transducers academically, I don't need it to be a transducer necessarily
just curious
Jigar Gosar
@jigargosar
Mar 29 2016 11:16
Hey guys, I had a question
var findByProps = R.curry(function (props, list) {
                        return R.find(R.whereEq(props), list);
                    });
is there a more consise way to wirte this?
I am very new to functional programming.
Raine Virta
@raine
Mar 29 2016 11:17
R.useWith(R.find, [ R.whereEq, R.identity ])
Jigar Gosar
@jigargosar
Mar 29 2016 11:18
@raine thanks. will look into those methods.
I keep wondering, where could I use all the functions in the lib, but end up writing mostly imperative code. And guide which gives many examples would be very helpful.
Jigar Gosar
@jigargosar
Mar 29 2016 11:19
or some open source project that uses R heavily.
@kujon thanks, I had gone through that list, will go over it again.
Jakub Korzeniowski
@kujon
Mar 29 2016 11:23
Jigar Gosar
@jigargosar
Mar 29 2016 11:25
@kujon tx, I wanted to explore os prj. to learn how to use r better.
Stefano Vozza
@svozza
Mar 29 2016 11:48
Jigar Gosar
@jigargosar
Mar 29 2016 12:00
@svozza nice one, let me see if I can actually use it, to refactor my existing R code. :)
BTW: I love Ramda
it got me closer and closer to thinking functional, which I was struggling with for a long time. But there is a long way to go!
Denys Mikhalenko
@prontiol
Mar 29 2016 12:02
functional programming is very egoistic
Raine Virta
@raine
Mar 29 2016 12:04
what makes you say that
Denys Mikhalenko
@prontiol
Mar 29 2016 12:11
because it's pretty hard to understand someone's logic in complex fp expressions
data flow is way not that obvious as in imperative programming
Lewis
@6ewis
Mar 29 2016 12:46
This message was deleted
@Bradcomp
http://goo.gl/9GdjGv what am i doing wrong?
Hardy Jones
@joneshf
Mar 29 2016 12:52
@6ewis R.indexof takes two arguments.
R.indexOf
Hardy Jones
@joneshf
Mar 29 2016 12:52
A function is never equal to 1, thus everything is filtered out.
Lewis
@6ewis
Mar 29 2016 12:53
right i figured out thanks,
@joneshf do we have atindex ? or im left ot have to use splice
Hardy Jones
@joneshf
Mar 29 2016 12:53
@JAForbes do you control this data?
@6ewis there's R.addIndex
R.addIndex
Hardy Jones
@joneshf
Mar 29 2016 12:55
@ram-bot
const indexToRemove = 1;
R.addIndex(R.filter)((_, n) => n !== indexToRemove,  ['foo', 'bar', 'baz']);
ram-bot
@ram-bot
Mar 29 2016 12:55
[ 'foo', 'baz' ]
Hardy Jones
@joneshf
Mar 29 2016 12:56
There's also a good chance that whatever you're doing could be made clearer with a different approach. That is usually the case for me when I find that I need an index for map or friends.
Lewis
@6ewis
Mar 29 2016 12:58
Hardy Jones
@joneshf
Mar 29 2016 12:58
@JAForbes if you control the data, you could make your life easier by using a better data type to begin with. Use an actual tree, rather than an approximation from objects and arrays.
Lewis
@6ewis
Mar 29 2016 12:58
@joneshf I'm learning more about ramda off somebody question
@joneshf can you explain the previous code posted?
Hardy Jones
@joneshf
Mar 29 2016 12:59
Mine or yours?
Lewis
@6ewis
Mar 29 2016 12:59
yours
Hardy Jones
@joneshf
Mar 29 2016 12:59
Sure.
Lewis
@6ewis
Mar 29 2016 13:00
@joneshf mine's not working - i don't understand something fundamental about ramda I guess
Hardy Jones
@joneshf
Mar 29 2016 13:00
The first argument to filter is a function a -> Boolean.
This a is whatever type the elements of the second argument are.
So in your case, the a here is String.
So the first argument to filter is a function String -> Boolean.
But you don't care about the String in this case.
You only care about its index.
So we use addIndex to modify filter.
addIndex changes how filter works by adding another argument to its function.
Lewis
@6ewis
Mar 29 2016 13:01
ah smart!
Hardy Jones
@joneshf
Mar 29 2016 13:02
Yeah.
So the first argument to addIndex(filter) is a function (String, Number) -> Boolean.
The Number being the index of the element in the array.
If the element's index matches the indexToRemove we say it's false. Otherwise it's true.
So addIndex(filter) removes that element from the array.
Hardy Jones
@joneshf
Mar 29 2016 13:08
In your last example, you're using each element as though it's the index of the element. But you don't get the index, you get the actual element itself. Also, you need to return a boolean value, not an array or null.
Lewis
@6ewis
Mar 29 2016 13:10
@joneshf thanks man you clarified it a lil bit better
Jakub Korzeniowski
@kujon
Mar 29 2016 13:41
I got a little bit negligent recently with following all fantasyland-compatible types implementations and will be starting a new project soon. I've been using ramda-fantasyso far, but this project is stale (not sure whether I should care, because it works seamlessly in production). I've heard some rumours of sanctuary + ramda-fantasy merge, but I've never been a fan of sanctuary's type checking. I've bumped into https://github.com/Avaq/Fluture, Fantasy Land org have got most of the types I need as separate packages, but again, not sure whether they're mostly PoCs or something authors think is production-ready. Is there a new 'standard' set of types emerging? It would be ideal to complement ramda with well maintained types, preferably from a single org. I currently use Maybe, Future, IO and Either extensively, but will probably need some more in the future.
Lewis
@6ewis
Mar 29 2016 13:44
This message was deleted
Hardy Jones
@joneshf
Mar 29 2016 13:46
@kujon what makes you think RF is stale?
And what makes you think FL libs are POCs?
Hardy Jones
@joneshf
Mar 29 2016 13:53
@6ewis what exactly are you wanting to do?
Lewis
@6ewis
Mar 29 2016 13:54
@joneshf same exact thing, I was just playing with it and trying to do it with my own logic
Hardy Jones
@joneshf
Mar 29 2016 13:56
ah
keep playing with it? :)
Lewis
@6ewis
Mar 29 2016 13:58
@joneshf what's the process you follow when you think about putting a sequence of functions together; something is not clicking. look at my link above, i find it quite cumbersome to do the oneliner from right to left
Jakub Korzeniowski
@kujon
Mar 29 2016 13:59
@joneshf there used to be a time where it sat at 0.2.0 for quite a while, even though there was some really useful activity in the repo. Maybe it was due to the project being in its really early stages. FL libs being PoCs - this was less of a statement, more of a question - I've seen people using them as such, and some of the FL repos seem to be demonstrators (https://github.com/fantasyland/fantasy-birds awesome, super informative, yet I can't expect people writing bluebird(x => x * 2)(x => x - 1)(3) in production code). Then, there is a case of @Avaq 's Fluture and some other implementations cropping up, so I'm wondering which ones are the best to use in production code.
Hardy Jones
@joneshf
Mar 29 2016 14:08
@6ewis I'm pretty ad-hoc with this stuff. One thing I do is look to see if there's anything that seems like map, filter, traverse, etc. And try to convert the data to use one of those.
Lewis
@6ewis
Mar 29 2016 14:08
@CrossEye let me know your approach too
Hardy Jones
@joneshf
Mar 29 2016 14:09
@6ewis another thing I'll do is work from both sides. Say I've got an array of objects, and I want a single object. I'll play with array stuff for a bit, then object stuff for a while. So I look at both ends until they meet in the middle.
Jigar Gosar
@jigargosar
Mar 29 2016 14:11
i have a nested object, with arrays, and objects in it. now I want to move an deep element from one array to another. is there some generic way to solve this problem without mutation?
object to be moved and all the arrays, are in one object graph.
I can find them using find methods. but how do I reconstruct the arrays without mutating them. and have the entire object graph preserved/copied.
think of an nested ui widgets object, which contains other widgets, I want to move one widget from one container to another. where container is an array. without modifying my root model graph. so that i can get new root graph and render it.
Jigar Gosar
@jigargosar
Mar 29 2016 14:16
I just need some guidance in the right direction, so that I can figure out on my own. Not looking for ready made solutions.
thanks in advance.
:)
Hardy Jones
@joneshf
Mar 29 2016 14:18
@6ewis another thing I do is look at the types and see if they even make sense. Many times it's hard to use ramda is because I'm feeding it types that are hard to work with.
Lewis
@6ewis
Mar 29 2016 14:23
@joneshf basically here is my issue http://goo.gl/LFFrXg , the code i write with ramda is so imperative that it defeats the purpose of me using ramda
@CrossEye @Bradcomp feel free to chip in when you get a minute ;), I think the more perspective I have the better I'll get at it
Hardy Jones
@joneshf
Mar 29 2016 14:28
Nah, I wouldn't say it defeats the purpose. Look how much mutation those lines have—none!
That's a win if you ask me.
Give it time I'd say.
Lewis
@6ewis
Mar 29 2016 14:29
@joneshf map,filter are functions that are natively available in es5 and they return new object so that would mean that i could achieve the same with plain javascript - no mutation
mutations is not a strong argument
currying,composition, and succinct syntax are appealing to me and that's what brought me to ramda ..but only if you know how to use it well :/
Hardy Jones
@joneshf
Mar 29 2016 14:34
There's no problem with using es5 things natively. I'm in the camp that you use the right tool for the job. If you don't want to bring in ramda because all you use is map, then don't do it. Just because you can possibly write something point free doesn't mean that you should make some complex ramda thing. If you find that you're doing the same thing multiple times, there's probably an abstraction in ramda that can help it there.
Jakub Korzeniowski
@kujon
Mar 29 2016 14:35
@jigargosar You could use lenses and write sth similar to: http://goo.gl/29CtFx
Hardy Jones
@joneshf
Mar 29 2016 14:35
mutation might not be a strong argument to you, but from my perspective it's one of the strongest.
Jakub Korzeniowski
@kujon
Mar 29 2016 14:35
I've used numbers in my example, but you could use anything else, just by changing the predicate and data structure
append could also be parametrised
Jigar Gosar
@jigargosar
Mar 29 2016 14:36
@kujon thanks, let me check them out.
@kujon thats some pretty heavy stuff for me. I though using functional programming will make things more concise, rather than this verbose. :(
Jakub Korzeniowski
@kujon
Mar 29 2016 14:40
I might have overcomplicated it, this was the first thing that cropped to my mind
Jigar Gosar
@jigargosar
Mar 29 2016 14:40
@kujon did you just write that example for me? thanks a lot.
Jakub Korzeniowski
@kujon
Mar 29 2016 14:40
yup
Jigar Gosar
@jigargosar
Mar 29 2016 14:41
:)
Jakub Korzeniowski
@kujon
Mar 29 2016 14:41
basically, sourceLens focuses on the array of widgets you want to remove from
view(sourceLens, atom); // > [1, 2, 3]
this + predicate allows you to find the item you are after:
compose(find(predicate), view(sourceLens))(atom); // > 3
targetLens is where you want to put stuff in, e.g.
set(targetLens, [7, 8, 9], atom) // > { baz: { qux: [7, 8, 9] }, /*the rest of stuff here*/ }
// or
over(targetLens, append(3), atom) // > { baz: { qux: [4, 5, 6, 3] }, /*the rest of stuff here*/ }
now you just combine finding, adding and removing together
Jakub Korzeniowski
@kujon
Mar 29 2016 14:48
// addStuff :: Atom -> Atom
const addStuff = 
    converge(over(target),
             [compose(append, find(predicate), view(source)),
              identity]);
This will pass the whole object through 2 functions (those in the array), in order to generate missing arguments for over(target). Generated arguments will be append(3) and atom respectively.
// removeStuff :: Atom -> Atom
const removeStuff = over(source, reject(predicate));
This will accept the object as a whole and run reject(predicate, sourceArray) on your source array. Because both elements of the pipe take the whole object and return its modified copy, you can pipe them together.
does this help?
*unless, someone's got a simpler idea on how to solve that problem
Jakub Korzeniowski
@kujon
Mar 29 2016 15:13
@jigargosar also, if you parametrise append like so for example http://goo.gl/icDJyK, you end up getting a function which works on any data structure, with any way of finding element to swap and any way of putting it in its new place.
Brad Compton (he/him)
@Bradcomp
Mar 29 2016 15:30
@6ewis Are you just going for this?
// {hashtags: ['foo', 'bar', 'baz']}, indexToRemove = 1; result {hashtags: {'foo', 'baz']}
Lewis
@6ewis
Mar 29 2016 15:48
@Bradcomp i had a good dicussion about it with @joneshf if you scroll up - but yea in a nutshell i want to write it point -free and succinctly and follow your reasoning so that i can emulate it when i have similar transformations to do
Brad Compton (he/him)
@Bradcomp
Mar 29 2016 15:50
@6ewis It isn't point free, but here's my first thought: http://goo.gl/v2XWCq
I know a lot of people here advocate for lenses, but evolve is pretty cool if you have some set of transformations to perform on an object
R.evolve
Lewis
@6ewis
Mar 29 2016 15:55
@Bradcomp so you're passing the index to evolve. that haskell notation is a pain point, I can't read it
R.evolve ∷ {k: (v → v)} → {k: v} → {k: v} => close to Arabic
Jigar Gosar
@jigargosar
Mar 29 2016 16:00
var someLens = R.compose( R.lensProp('days'), R.lensIndex(1), R.lensProp('events'), R.lensIndex(1) ); console.log(view(someLens, scheduleJSON));
Lewis
@6ewis
Mar 29 2016 16:00
@Bradcomp thanks it might not be point free but it's succinct; it's better than http://goo.gl/7OhLDb
Jigar Gosar
@jigargosar
Mar 29 2016 16:01
var someLens = R.compose(
            R.lensProp('days'),
            R.lensIndex(1),
            R.lensProp('events'),
            R.lensIndex(1)
        );
        console.log(view(someLens, scheduleJSON));
Brad Compton (he/him)
@Bradcomp
Mar 29 2016 16:01
@6ewis The notation can be a pain, but you'll get there!
{k: (v -> v)} <- The first parameter is an object where the values are functions that take a single parameter
-> {k: v} <- The second parameter is a plain object
-> {k: v} <- The return type is a plain object
So here:
R.evolve({
  hashtags: R.remove(ndx, 1)
})
Jigar Gosar
@jigargosar
Mar 29 2016 16:01
is there some technique where I could dynamically compute day index and event index, based on some predicate?
Brad Compton (he/him)
@Bradcomp
Mar 29 2016 16:01
R.remove(ndx, 1) will take an array and remove the item at ndx
@6ewis That function is associated with the hashtags key, so it will be applied to the value of the hashtags key in the object we pass in
Lewis
@6ewis
Mar 29 2016 16:03
this solution is even better http://goo.gl/bE7kqM but i needed to justify using ramda
Jakub Korzeniowski
@kujon
Mar 29 2016 16:04
@jigargosar - findIndex
R.findIndex
Jigar Gosar
@jigargosar
Mar 29 2016 16:04
@kujon sorry I didnt check your other comments, will do now.
Lewis
@6ewis
Mar 29 2016 16:05
@Bradcomp thanks! i understand the notation better
Jigar Gosar
@jigargosar
Mar 29 2016 16:05
@kujon I was wondering how do I fit find index into this compose pipeline?
Lewis
@6ewis
Mar 29 2016 16:06
so R.findIndex would be --> first argument is anything that return a boolean, second argument an array, and the return type is a number?
Jigar Gosar
@jigargosar
Mar 29 2016 16:06
first I want to filter days, then I want to filter events.
so should I precompute these values, then use lens to locate the part that needs modification, and then apply over on it?
@kujon is that what you are suggesting?
@kujon precompute incices, componse lens to loacate element, use “over” function for modification. and chain these “over" functions for multiple modifications.
Jakub Korzeniowski
@kujon
Mar 29 2016 16:12
@jigargosar - you could also use just R.lens, e.g.:
// isInterestingDay :: Day -> Boolean
const isInterestingDay = day => day.events.length > 0;
// interestingDayLens :: Lens [Day] Day
const interestingDayLens = R.lens(
   // this tells the lens how to get the focused element
   find(isInterestingDay),
   // this tells the lens how to set the new value of the focused element
   curry((day, days) => insert(findIndex(isInterestingDay, days), day, days))
);
Brad Compton (he/him)
@Bradcomp
Mar 29 2016 16:13
@6ewis You got it! The only thing I would add is that the first argument is a function that takes a single parameter of some type (a), and the array contains items of that same type
Jakub Korzeniowski
@kujon
Mar 29 2016 16:13
*also bear in mind that all of my examples assume that the element you are after will be found :D
@jigargosar - lensProp('x') is a shorthand for lens(prop('x'), assoc('x')) and lensIndex(1) is a shorthand for lens(nth(1), insert(1))
Lewis
@6ewis
Mar 29 2016 16:20
@Bradcomp thanks you've been really helpful
Jigar Gosar
@jigargosar
Mar 29 2016 16:21
@kujon thanks, this is very helpful.
Jakub Korzeniowski
@kujon
Mar 29 2016 16:22
I would actually be really glad to see whether anyone here has got a simpler and nicer solution, because I have a feeling the problem you're trying to solve might get quite complicated :D
Jigar Gosar
@jigargosar
Mar 29 2016 16:22
but the custom lens function looks bit verbose, precomputing indices seems like a shorter version.
@kujon me too, I would like to see some variations of this techique, to get better understanding, of how to compose these functional elements. It seems composition is the biggest challenge in FP ;)
Jakub Korzeniowski
@kujon
Mar 29 2016 16:30
@jigargosar the disadvantage of precomputing indices is that you need the data in order to be able to create the lens.
I guess it all depends on how generic you want your target solution to be in the end
Dejan Toteff
@selfrefactor
Mar 29 2016 17:09
This message was deleted
This message was deleted
This message was deleted
Aldwin Vlasblom
@Avaq
Mar 29 2016 17:11
@selfrefactor You can edit your messages (up-arrow to edit). You use three consequetive backticks to denote a multiline block of code. :)
Dejan Toteff
@selfrefactor
Mar 29 2016 17:11
txs, I can't figure out why the code is not displayed
I need advice can I make composeP take array of promise returning function, instead of declaring it, instead of what I did below:
const R = require('ramda')
let commands = ["git push","git commit -m root", "git add . --all"]

R.composeP(willRunCommand, willRunCommand, willRunCommand)(commands.length - 1).then((data) => {
    console.log("final",data)
})
function willRunCommand(indexIs) {
    let commandIs = commands[indexIs]
    return new Promise(function(resolve, reject) {
            let proc = execSync(commandIs)
      return resolve(--indexIs)
    })
}
function execSync(data){
   //empty mock fn
}
Aldwin Vlasblom
@Avaq
Mar 29 2016 17:14
:+1:
Jakub Korzeniowski
@kujon
Mar 29 2016 17:15
would anyone mind helping me out with this one pls https://gitter.im/ramda/ramda?at=56fa86038d2a72471b7b126f ?
Brad Compton (he/him)
@Bradcomp
Mar 29 2016 17:23
@selfrefactor Could you use apply?
R.apply
Aldwin Vlasblom
@Avaq
Mar 29 2016 17:25
@selfrefactor If I were you I'd reduce my commands into a single Promise chain:
const R = require('ramda')
let commands = ["git push","git commit -m root", "git add . --all"]

//I'm guessing the execSync is temporary
const runCommand = command =>
  new Promise(resolve => resolve(execSync(command)));

//Sticks all commands in the array together using `.then(...).then(...)`:
const runAllCommands = R.reduce(
  (p, command) => p.then(() => runCommand(command)),
  Promise.resolve()
);

runAllCommands(commands).then(() => console.log('All done'))
Denys Mikhalenko
@prontiol
Mar 29 2016 17:31
take a look at R.composeP, maybe you can use it instead of R.reduce?
Dejan Toteff
@selfrefactor
Mar 29 2016 18:29
txs @Avaq seems better and it is better :smile:
Dejan Toteff
@selfrefactor
Mar 29 2016 18:35
@Bradcomp R.apply looks as 100% fit, I think I will make it work. Thanks for the tip!
Brad Compton (he/him)
@Bradcomp
Mar 29 2016 18:57
@selfrefactor :+1:
Kurtis Rainbolt-Greene
@krainboltgreene
Mar 29 2016 19:40
Hey, I upgraded from 0.17.z to 0.19.z and my application broke.
Why isn't ramda following SEMVER?
(Specifically I depended on mapObj)
Stefano Vozza
@svozza
Mar 29 2016 19:44
mapObj is now called map
Aldwin Vlasblom
@Avaq
Mar 29 2016 19:45
@krainboltgreene 0.17.x to 0.19.x is a breaking change according to SEMVER.
Stefano Vozza
@svozza
Mar 29 2016 19:45
Or more correctly, its functionality now resides in that function
Aldwin Vlasblom
@Avaq
Mar 29 2016 19:48
It's major.minor.patch or 0.major.minor. So 0.1.0 to 0.2.0 is a major version increment. NPM follows these rules, so if you had set ^0.17.0 in your package.json then npm install wouldn't have installed 0.19.x.
Kurtis Rainbolt-Greene
@krainboltgreene
Mar 29 2016 19:52
@svozza Yeah, I know that.
@Avaq No, it's not.
Ugh.
Allowing 0.X was the worst choice ever.
Roman Pominov
@rpominov
Mar 29 2016 20:49
Before 1.0.0 you don't have to follow semver according to semver.
But there is a common convention that before 1.0.0 it's 0.major.minor
LeonineKing1199
@LeonineKing1199
Mar 29 2016 21:02
Hey, I saw that the transduction implementation got improved!
That's pretty neat. I like Ramda's type-traits-y approach to creating transducers in JS
Jakub Korzeniowski
@kujon
Mar 29 2016 21:08
Ramda's upgrade guides are pretty decent, find and replace should fix most of the issues
Kurtis Rainbolt-Greene
@krainboltgreene
Mar 29 2016 22:22
Mihai Târnovan
@mtarnovan
Mar 29 2016 23:34
is there a way to transform a function into a function of a given arity without currying it? basically, I think I need something like this: https://github.com/ramda/ramda/blob/master/src/internal/_arity.js but that doesn't seem to be exposed in the public API
Scott Sauyet
@CrossEye
Mar 29 2016 23:42
nAry
Mihai Târnovan
@mtarnovan
Mar 29 2016 23:42
@CrossEye thanks
Scott Sauyet
@CrossEye
Mar 29 2016 23:42
@ram-bot nAry
ram-bot
@ram-bot
Mar 29 2016 23:42
[Function: f2]
Scott Sauyet
@CrossEye
Mar 29 2016 23:43
still forget how to get the bot to give the sig... oh well it's on the docs.
It's slightly different from arity.
arity passes through any additional arguments you supply. nAry caps the arguments at the number you supply.
@ram-bot nAry
Mihai Târnovan
@mtarnovan
Mar 29 2016 23:45
I'm trying to write a function that wraps api calls made with a promise-based library (axios), with caching to localStorage, I have something like this:
const cacheApiCall = (fn, expiry = {'minutes': 30}) => {
  return R.nAry(fn.length, function () {
    let key = [fn.name, R.toString(arguments)].join()
    let cached = JSON.parse(localStorage.getItem(key))
    if (cached !== null && cached.expiresAt >= moment().unix()) {
      return Promise.resolve(cached.response)
    }

    let promise = fn.apply(this, arguments)
    return promise
      .then(function(response) {
        let expiresAt = moment().add(expiry).unix()
        localStorage.setItem(key, JSON.stringify({ expiresAt, response}))
        return Promise.resolve(response)
      })
      .catch(function(error) {
        return Promise.reject(error)
      })
  })
}
how awful is this? :)
i was calling R.curryN before, I replaced it with R.nAry now
I'm also not sure it's wise to use fn.name in the cache key...
Mihai Târnovan
@mtarnovan
Mar 29 2016 23:52
R.nAry
Mihai Târnovan
@mtarnovan
Mar 29 2016 23:55
ramda seems very cool btw, congrats to the devs :clap: