6 ms·
(Disclosure: one of the authors of Ramda here, so I may well be biased toward a very different approach.) This is an interesting approach, but I get caught rig
by CrossEye 11y ago
(Disclosure: one of the authors of Ramda here, so I may well be biased toward a very different approach.)
This is an interesting approach, but I get caught right at the beginning, where you say "What you'd really want to do is this:
items
.filter(isOk)
.map(toOtherType)
.flatten()
But what I really want to do is build a reusable function:
var process = seq(filter(isOk), map(toOtherType), flatten);
So I can at my leisure call
process(items);
Or later put `process` in another sequence, or do something like:
map(process, groupsOfItems)
And I don't see that Trine helps with that. Am I missing the way to use Trine to build functions, or do I simply have to wrap up a Trine construct in a function that takes a parameter, does its Trine magic, and returns that result?
- yanis_t 11y agoAgreed. And btw thank you for Ramda, which is a very beautiful thing. Too sad in day-to-day web development lodash is just enough.
- CrossEye 11y agoThat's not sad. Use the tools that work for you. It was finding that those tools were no longer supporting the way I wanted to work that got me started on Ramda. I'm guessing the same is true for the author of Trine.
- jgord 11y agoand thanks again for Ramda .. I use it daily for real work, back and front end.
- smrtinsert 11y agoIf you mean using frameworks to display data, then yes. For anything substantial I'd use ramda over lodash.
- jdd 11y agoWhy not both? lodash is modular so you can use the bits you need. There's also a flavor with auto-curried iteratee-first/data-last methods too https://www.npmjs.com/package/lodash-fp https://www.npmjs.com/package/lodash-fp
- icebraining 11y agoSeems like you could just do var process = items => items.filter(isOk).map(toOtherType).flatten()
- deleted 11y ago[deleted]
- CrossEye 11y agoThe difference starts to show when you want to partially apply some values. // process1 :: (Item -> Bool) -> [Item] -> [OtherType] // process2 :: [Item] -> [OtherType] process1(isOk, items); //=> [otherType1, otherType2, ...] process2(items); //=> [otherType1, otherType2, ...] var processR1 = seq(filter, map(toOtherType), flatten); var processR2 = processR1(isOk); var processT1 = (isOk, items) => items.filter(isOk).map(toOtherType).flatten() var processT2 = items => processT1(isOk, items) That's why I'm wondering if there's some easier way to do this.
- icebraining 11y agoI believe you can use partial() from this post[1] to do something like this: var processT1 = (isOk, items) => items.filter(isOk).map(toOtherType).flatten(); var processT2 = partial(processT1, isOk); http://benalman.com/news/2012/09/partial-application-in-javascript/#partial-application-from-the-left http://benalman.com/news/2012/09/partial-application-in-java...
- tolmasky 11y agoI believe you showed in one of your demonstrations (or someone else showing ramda), a very simple elegant example: > sum = reduce(add, 0) > sum([1,10,20]) With something like trine, composition can only happen really happen at usage-time, while with Ramda it allows you to reason about the operations separate from the data. I suppose trine could achieve the same by further complicating with some sort of dummy data: sum = __placeholder__.reduce(add, 0); [1,10,20].::sum() But this gets difficult because __placeholder__.reduce itself needs to return something that can be chained (certainly doable to return a function that is also a dummy object I suppose?). But anyways, to me this starts looking more and more complex, and making it harder to reason about constructing (composing) NEW functions from existing ones.
- CrossEye 11y agoThat is ceratainly one of my standard examples. The best answer to this seems to be simply: var sum = ls => ls.reduce(add, 0) ISTM that this is neither as elegant nor as easy to reason about, but it's also not horrible. It really moves away from the easy association that Ramda makes between var currentTotal = reduce(add, 0, nbrs); and var sum = reduce(add, 0); //=> :: [Number] -> Number Of course this arrow syntax is ES6 (or transpiler) only, but the library is predicated on that notion. Ramda is a bit of an oddity, still maintaining compatibility with ES3 - ES6.
- quinnirill 11y agoTrine can actually already do this particular example: sum = reduce::partial(add, 0); [1,10,20]::sum();
- sramsay 11y ago(Disclosure: big fan of Ramda here) That's exactly where I got caught too. I just don't see why I really want to do it that way at all. My favorite thing about Underscore/Lodash/Ramda is function composition. This seems like a (syntactical) move away from that . . .
- quinnirill 11y ago(Disclosure, Trine author here, and also admittedly very inspired by Ramda.) I actually used Ramda quite extensively a while back, because I was convinced it was the right way. However, a while after looking at stack traces that lead to Ramda and not even myself understanding my where each parameter in my own code goes, I decided to stop using it and also dropped these features from Trine. Trine has partial, and that's as far as magic goes, in fact I wanted to make it as far from magical as possible. I think plain old functions are the best form of function composition, albeit I'd love for the syntax to be terser. They're easy to read and easy to reason about, also easy to reorder, no need for higher order functions that go in the middle.
- CrossEye 11y agoIt's a funny world. Each of us is looking at the other library thinking there's too much magic involved. :-) Ramda is [considering a technique][1] that would significantly reduce call stacks. But there is nothing likely to help with you understand parameter orders of your functions. Many users annotate their functions with something like Haskell signatures. Thank you for bringing forth another interesting library. I'll be following your progress. Best of luck! [1]: https://github.com/ramda/ramda/pull/907 https://github.com/ramda/ramda/pull/907
- quinnirill 11y ago> It's a funny world. Each of us is looking at the other library thinking there's too much magic involved. :-) Heh - I think what feels like magic is the syntax that Trine is presuming, which admittedly might seem magical before trying it out. :) The library itself is just a collection of very primitive methods (with the exception of partial()). > Ramda is [considering a technique][1] that would significantly reduce call stacks. That's good to hear! But what I'd really like to see is something that would make the stack trace have a reference to the function definition site, e.g. if I have an error like var getIds = map(prop("id")); var ids = getIds([{ id: 1 }, null, { id: 2 }]); the stack trace would also show the definition site of getIds. This is what I get when I compose functions just using the vanilla JS syntax: function getIds (items) { return items.map(function (item) { return item.id; // the stack trace will point here, and I can also add a breakpoint here without it stopping on every unrelated prop() call }); } Like I mentioned on several occasions here, I'm hoping for JS to get simpler unbound function syntax, which would work well with Trine, and still have the aforementioned benefits: let getIds = -> this::map(-> this.id); > Best of luck! Thank you, and likewise! <3
- quinnirill 11y agoWith Trine this would be function process () { return this ::filter(isOk) ::map(toOtherType) ::flatten(); } and then later: groupsOfItems::map(process); Granted, the `flatten` function is not in the Trine yet, somehow forgot that from the initial release.
- CrossEye 11y agoOk, that helps make it a bit more palatable to me. Thanks for the information. One question, though: How do user functions interact in here? If you didn't include `flatten`, but I had my own version of it, would it be straightforward for me to build `process` using my own `flatten`? Do I have to modify some Trine objects, or can I use some simple function references? Obviously I haven't yet actually dug into the Trine code. Perhaps this weekend.
- quinnirill 11y agoHappy to help! Yes, you can use just simple function references, e.g. you could just define flatten as so function * flatten () { for ( const item of this ) { yield * item; } } And it would work just like it was part of Trine - in fact that's probably how it's going to be implemented in Trine. The chaining is not a feature of Trine, but the function bind syntax proposal ( https://github.com/zenparsing/es-function-bind https://github.com/zenparsing/es-function-bind ), Trine has merely been designed to work well with this syntax.