Closed DrBoolean closed 7 years ago
Just curious, when you read this chapter 3, did you see the part about spreadArgs(..)
? I added the "Spread 'Em Out" section earlier today and I wasn't sure if it was there when you read or not.
I think your points about how printIf(..)
would typically have been defined are spot on.
But I think they actually highlight something of the difference at the very heart of this book. That is to say, the desire to have a printIf(..)
that takes two arguments (aka, not curried) -- thereby motivating the need for an uncurry(..)
-- is because the style of code here, I call "FP Light", tries to look more balanced like normal (imperative) JS but infused with FP goodness.
The goal of "FP Light" is not strictly adherent/canonical FP, but rather a compromise where FP is used less formally to improve existing imperative JS while not paving over its overall essence in that rebalancing.
I wonder if perhaps I should actually add a short section here to make this exact point, showing both my version and yours for comparison, thereby pointing out to the reader not only the things you mention here (like currying with data-last, etc), but also reinforcing what our goal with this specific book and style of code are.
I did see the Spread section - I refreshed later that day and thought I'd accidentally skipped it ha. There is one typo, btw: "imcompatible". Anyways, I dig it - just setting up a bunch of function utils for the further chapters and that totally belongs here.
For the printIf
stuff... this is a good discussion to get me on the same page. It's interesting territory since the mentality is not just "port haskell wholesale" :)
My only (grain of salt) suggestion there, then, might be to change the signature to printIf(pred, msg)
so one doesn't have to reverseArgs
to make it compatible with when
. It would read a little more englishy as well (i.e. printIf(isShortEnough, msg1)
). Though I suppose that's the point of the chapter so I can't disagree with leaving things be.
I'll remind myself of the lite
moving forward.
P.S. I'm going to use "englishy" from now on. What a word!
:) good suggestions, I may change. thanks!
Hey,
great chapter btw. I just want to ask about:
function partialRight( fn, ...presetArgs ) {
return reverseArgs(
partial( reverseArgs( fn ), ...presetArgs.reverse() )
);
}
if it can be rewritten like:
function partialRight(fn, ...presetArgs) {
return (...laterArgs) => fn(...laterArgs, ...presetArgs.reverse())
}
Thanks
@MajoDurco
Almost, except for two things... for one, I was trying to illustrate a usage of reverseArgs(..)
, and for another, the final reverse()
in your example isn't appropriate. Here's an example that shows the difference between the two. Should print "1 10 100 1000", but with your's, prints "1 10 1000 100".
function foo(a,b,c,d) {
console.log( a, b, c, d );
}
var f = partialRight( foo, 100, 1000 );
f( 1, 10 );
Loved this chapter. I feel it really gets the reader excited about this stuff!
What follows is a collection of mostly unnecessary ideas rather than "tech edits". I thought the tech was spot on and the examples were great so not much to do there. Either way, here are some thoughts:
1) You demonstrate equational reasoning several times both explicitly and implicitly.
partiallyApplied
definitionsprintIf
refactor.I wonder if it's worth a mention that FP goes out of its way to preserve equational reasoning. Not sure if you'd want that, just saying something since these are great examples of it in action.
If it is a thing you'd want to consider, maybe also make it explicit each time, formally, instead of using english to explain refactorings:
Anyways, just a thought. I understand this is supposed to be an informal book so no worries if this is too mathy - just something to consider so the reader gets a glimmer of the whole "reasoning about" thing and sees why purity can be so important later on.
2) That
_
inp1.then( foo ).then( _=>p2 ).then( bar );
may confuse someI get the "why the underscore argument?" question a lot. Maybe a note that
_
is often used to mean "ignored parameter" in FP would be good or just move to() => p2
.3) "The advantage of currying here is being able to do something like curriedSum(1)(2)(3), which returns a function".
This line didn't quite drive home the distinction between partial and curry for me. I see the main difference/advantage is that currying is used at definition time and partialApplication is used "on the fly" by the caller. I suppose that's implied by the examples, but might be worthwhile to spell out since they are so similar.
4) "Don't just assume that
uncurry(curry(f))
has the same behavior asf
".This is true for some libs, but lots do strive to make that isomorphism / adjunction (an iso between homSets) work, which then gives rise to the reader/writer monads (and their respective comonads). In any case, I'd mention it's false for this implementation only since it is true for some other libs.
5) Should it say something to the effect of "When currying, it's often useful to analyze argument position and put the "data" last". And "Usually one curries everywhere in this style". These techniques combined usually sidesteps the need for
uncurry
,partialRight
, andreverseArgs
".I absolutely love how the
printIf
example ties in everything from the chapter. It is built up beautifully from the prior concepts. Although, having written code like this for a while, I found myself asking "why haven't I encountered thereverse/partialRight/uncurry
pattern very often?"I think it's two things:
uncurry
orpartial
partialRight
is almost never necessary. On rare occasions, like thewhen
example,flip()
usually does the trick.So the common result in a ramda or haskell app would be something like:
var printIf = flip( when )( output );
With the full code being:
The tools here are worthwhile and valid, I just don't end up encountering the situation much in day-to-day code for the reasons stated above.
I'm not sure what to do with all of these thoughts and ideas, but I'm happy to have shared them. Either way if you decide to adopt them or not, I won't have emotions about it; just wanted to share my brain dump after reading.
Again, great chapter!