Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Jan 31 22:17
    CrossEye commented #2779
  • Jan 31 21:04
    ArturAralin commented #2779
  • Jan 31 20:08
    CrossEye commented #2779
  • Jan 31 18:56
    buzzdecafe commented #2631
  • Jan 31 18:09
    ArturAralin commented #2779
  • Jan 31 16:18
    CrossEye commented #2779
  • Jan 31 16:10
    CrossEye commented #2631
  • Jan 31 16:06
    CrossEye commented #2777
  • Jan 31 14:44
    ArturAralin opened #2779
  • Jan 31 07:39
    inferusvv commented #2631
  • Jan 31 03:07
    sespinozj commented #2771
  • Jan 31 02:33
    machad0 commented #2771
  • Jan 31 02:26
    JeffreyChan commented #2777
  • Jan 30 14:30
    CrossEye closed #2777
  • Jan 30 12:13
    vanyadymousky updated the wiki
  • Jan 30 01:42
    JeffreyChan commented #2777
  • Jan 29 21:06
    vanyadymousky updated the wiki
  • Jan 29 16:28
    CrossEye commented #2777
  • Jan 29 15:50
    mbostock commented #2772
  • Jan 29 15:48
    CrossEye commented #2772
Martin Algesten
@algesten
@00Davo I have this idea that I want promises but I don't want to see them. if I resort to long .then-chains I failed. I rather have a ppipe chain of simple functions that I can test with straight function application.
granted it doesn't work well if the IO is in the middle.
Danielle McLean
@00dani
Right, and I agree to a point - I've got a ppipe-esque function in my current project too. But shouldn't you still be passing promises to the pipeline to test it?
Martin Algesten
@algesten
I like the idea that whether I test with a promise or not is irrelevant. promise in - promise out. or normal value in - normal value out.
Danielle McLean
@00dani
Oh, wait, your pliftreturns a value synchronously when you only pass regular values to the function in the first place. So the whole pipeline stays synchronous if you never use a promise, gotcha.
Martin Algesten
@algesten
yes. that's it.
I can pretend I don't use promises :)
Danielle McLean
@00dani
I generally like to be "safer" and always return a promise from anything that might be async, even if it isn't for some arguments, but if you're consistently using plift and such I suppose it doesn't actually matter.
Martin Algesten
@algesten
it's an idea. I have road tested it a bit and its sort of neat.
John-David Dalton
@jdalton
Ya converge and useWith are essentially the same. It comes down to one passes the transforms a single argument of the index of the transform and the other passes it all arguments. So I'm trying to come up with a common name that describes that (tough). I'll keep kicking it around.
Raine Virta
@raine
00Davo: what if the function that returns the promise is private to the module, do you use rewire or something to replace it with mock implementation?
and by module i mean the file that exports something else that uses the private function in a pipeline
Danielle McLean
@00dani
Something like that, yeah. But if you're writing a mostly-pure pipeline that happens to do one impure action in the middle, it'd probably be a good idea to parameterise it on the impure function anyway? Maybe make the usual source of the promise a default argument, and pass a replacement for it in unit tests.
Scott Sauyet
@CrossEye

Although I recognize that there's an abstraction where useWith and converge are quite similar, my mental models of them are so different that it's hard to think of them as even related, except in that they both offer extensions to the notion of compose.

To me, useWith is all about running transformations on each of the parameters before supplying them to the main function; the focus is clearly on the main function. But converge is about running a number of functions against the same data, and then at the end, almost incidentally, combining their results; the focus is on the individual transformations.

Of course this is only a matter of perspective, and it's certainly no more or less valid than the notion that @jdalton is proposing based on potentially similar implementations. But it's interesting to realize how different such perspectives can be.

John-David Dalton
@jdalton
@CrossEye I think of them as modifiers on a function (kinda like arity, arg order, partially applied args, curried state) I think I could store them in metadata if needed
Scott Sauyet
@CrossEye
@jdalton: Understood, but my mental model doesn't really allow that for converge. The focus there is on the individual functions, and not on the one that combines the results. As I said, it's just a matter of focus... and of course, a matter of opinion.
John-David Dalton
@jdalton
I found a neat example for useWith (aka modArgs) in ld land
var assign = _.partial(_.modArgs(_.assign, Object), null);
super neat!
Scott Sauyet
@CrossEye
I'll try to wrap my head around that when I'm in front of a computer. Too hard to try to understand the types and signatures on my phone.
Raine Virta
@raine

@00Davo

Maybe make the usual source of the promise a default argument, and pass a replacement for it in unit tests.

It currently looks like this,

module.exports = (payload) =>
  readTemplates(payload.type, payload.site)
    .then(buildEmailOptions(payload))
    .then(transporter.sendMailAsync.bind(transporter));

readTemplates is the impure one. did you mean that in this case, readTemplates would be passed as an argument to the exported function?

John-David Dalton
@jdalton
I think I've settled on modArgs and modArgsSet
Scott Sauyet
@CrossEye
@jdalton: I'm glad you've found something you like. It's too bad it's not something I think would fly for Ramda as well, but that's not a very big deal. I will have to see what others think of disperse. It seems that converge is already pretty well accepted.
John-David Dalton
@jdalton
Ya i dig it, looking at the API you already get a hint of what it will be doing modArgs modifying args, modArgsSet modifying a set of args. It also shows their close relationship so woot. I don't dig the sS bit of modArgsSet or using Set but it's short and gets the point across.
Raine Virta
@raine
anyone found this useful? http://www.contractsjs.org/
Danielle McLean
@00dani
@raine That's my thinking, yeah. Make it (payload, templateSource) => or something like that, and if the second argument's not passed you can use readTemplates as the source?
Scott Sauyet
@CrossEye
@raine: never tried it. Never really impressed by Eiffel, and this doesn't hold a great deal of appeal, although I am a bit curious.
Raine Virta
@raine
00Davo: interesting approach. i've always kind of thought that changing code to accommodate testing is bad but i'm going to try this approach. the alternative would be to couple tests to private parts of the code, in order for the tests to know which function does the impure stuff
Danielle McLean
@00dani
I figure it's basically just injecting a dependency, which is Good Design™ as much as it is specifically accommodating testing.
hemanth.hm
@hemanth
If you were to pick and imperative code and convert it to functional using ramda to explain the features of FP, which code would that be?
Simon Friis Vindum
@paldepind

@hemanth Depends on the size of the example

const max = R.reduce(R.max, 0, [3, 4, 1, 9 ,3]);

Imperative code would be something like this:

let max = 0;
for (let i of [3, 4, 1, 9 ,3]) { max = R.max(max, i); }
hemanth.hm
@hemanth
@paldepind looking for some example that would involve the basics, so it would be nice to explain it to a huge group who are new to FP, thanks!
Explaining the hows are easy, whys are though...
Simon Friis Vindum
@paldepind
The important difference in the example above is that in the FP code I can let max be const. In the other I have to make it a let. IMO this highlights the key difference between imperative and functional code. The first is a definition of what max is. The second is a sequence of steps that ends of with max having the correct value.
hemanth.hm
@hemanth
@paldepind Why not Math.max.apply(null,[3,4,1,9,3]) ?
Simon Friis Vindum
@paldepind
@hemanth Well. Let's say we don't have that function and that we want to define it.
hemanth.hm
@hemanth
hmm
Simon Friis Vindum
@paldepind
Of course that example in itself does not really show how FP is better.
hemanth.hm
@hemanth
Agree, will have set of examples
BTW, is this functional enough?
let map = function(f, args) {
  let [x, ...xs] = args;
  if (x === void 0) {
    return [];
  } else {
    return [f(x)].concat([].slice.call(map(f, xs)));
  }
};
if let [x,...xs] = args is avoided it would be nice...
Simon Friis Vindum
@paldepind
@hemanth Well. I don't like it. You get the head and the tail of the list before you check if it is empty. I'd much rather do the destructuring after you've checked if the list is empty.
hemanth.hm
@hemanth
@paldepind Makes sense, trying to implement reduce in a similar manner
Simon Friis Vindum
@paldepind
Something like this:
const map = (f, list) =>
  list.length > 0 ? [f(list[0])].concat(map(f, list.slice(1)) : []
hemanth.hm
@hemanth
^ I'm getting an error on that. Like to use the spread operator rather thanslice
Simon Friis Vindum
@paldepind
I didn't test it :S I think spread would only complicate things in this case.
I'm missing a parentheses after slice.
hemanth.hm
@hemanth
@paldepind Nice, I would rather have list first and fn next in the param order
Jack Firth
@jackfirth
@raine @CrossEye Re contracts and Eiffel - that implementation is significantly different from Eiffel's in that it allows contracts for higher order functions - you can specify "this function accepts a function of two arguments that returns a boolean" in the contract. Makes it a huge win for FP, and drastically improves error messages. Eiffel contracts are more "before calling this, state is X, after calling, state is Y"
hemanth.hm
@hemanth
@paldepind slice doesn't mutate the array, nice.