by

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 2019 22:17
    CrossEye commented #2779
  • Jan 31 2019 21:04
    ArturAralin commented #2779
  • Jan 31 2019 20:08
    CrossEye commented #2779
  • Jan 31 2019 18:56
    buzzdecafe commented #2631
  • Jan 31 2019 18:09
    ArturAralin commented #2779
  • Jan 31 2019 16:18
    CrossEye commented #2779
  • Jan 31 2019 16:10
    CrossEye commented #2631
  • Jan 31 2019 16:06
    CrossEye commented #2777
  • Jan 31 2019 14:44
    ArturAralin opened #2779
  • Jan 31 2019 07:39
    inferusvv commented #2631
  • Jan 31 2019 03:07
    sespinozj commented #2771
  • Jan 31 2019 02:33
    machad0 commented #2771
  • Jan 31 2019 02:26
    JeffreyChan commented #2777
  • Jan 30 2019 14:30
    CrossEye closed #2777
  • Jan 30 2019 12:13
    vanyadymousky updated the wiki
  • Jan 30 2019 01:42
    JeffreyChan commented #2777
  • Jan 29 2019 21:06
    vanyadymousky updated the wiki
  • Jan 29 2019 16:28
    CrossEye commented #2777
  • Jan 29 2019 15:50
    mbostock commented #2772
  • Jan 29 2019 15:48
    CrossEye commented #2772
Raine Virta
@raine
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.
Dave Keen
@ccapndave
Hey everyone - is there a way to write R.pipe(R.prop('rows'), R.pluck('doc')) with a single function?
Scott Sauyet
@CrossEye
@jackfirth: I only glanced at the docs, and didn't dig very deep. While I've never bought the notion that the only good FP is strongly typed FP, I certainly have some sympathy for attempts to add stronger typing to JS. After all Ramda's avoidance of overloading and of optional parameters certainly works along those lines. But I'm usually not that intetested in attempts to add real strong typing to JS. I'll have to take another look at this one though.
Hardy Jones
@joneshf

@raine another options is to add another function, one that performs the algorithm, like @00Davo said:

baseAlgorithm = (read, payload) =>
  read(payload.type, payload.site)
    .then(buildEmailOptions(payload))
    .then(transporter.sendMailAsync.bind(transporter));

ioAlgorithm = (payload) =>
  baseAlgorithm(readTemplates, payload);

module.exports = {baseAlgorithm, ioAlgorithm};

Then you can test the algorithm with a unit test, and the io version with an integration test.

But you still have the shortcut function that you care about
If yu don't want to expand the public api, then shove the base algorithm in some internal file somewhere, or move it to an entirely separate module and depend on it.
Tamas
@bling5630
hey guys, do you have any ideas how can I solve this much more elegant? thanks,Tamas

input is

['apple', 'the', 'one', 'two', 'three', 'elephant', 'whatever']

var filterByLength = R.filter(function(str) {

    return str.length > 3 && str.length < 6;
});

desired output is

['apple', 'three']
Hardy Jones
@joneshf
@bling5630 what do you view is inelegant about it?
Tamas
@bling5630
I just like a shorter one, what do you think about it?
Matthew Steedman
@knubie
@bling5630 if you're looking for a point-free solve something like this would work:
var filterByLength = R.filter(
  R.converge(
    R.and,
    R.compose(
      R.lt(3),
      R.prop('length')
    ),
    R.compose(
      R.gt(6),
      R.prop('length')
    )
  )
);
that's obviously longer, though
Aldwin Vlasblom
@Avaq
Something like R.filter(R.where({length: R.allPass([R.gt(6), R.lt(3)])})) is shorter.