-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spread the love: transduce + chain #2395
Comments
Would you like to submit a PR to update the docs to match other functions which mention transducer support? |
Sure. I guess that will simply involve adding:
? |
👍 |
whelp, glad we got that cleared up :| |
nonetheless, thanks for the excellent example! |
@kedashoe @buzzdecafe and @CrossEye Forgive me for this is more of a question, but one too long for gitter and one that others landing on this issue may benefit from. Chain branch isn't lazy.If you look at this revised example: const tapLog = R.tap( (what) => console.log(what) )
const suits = ['♠', '♥', '♦', '♣']
const ranks = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'J', 'Q', 'K', 'A']
const addRank = (suit) => R.map(concat(suit),ranks)
var transducer = R.compose(
R.chain(addRank),
tapLog,
R.take(2)
);
R.into([], transducer, suits); Then you probably know that This is not an issue, unless you are mapping 680k graph nodes. Can this be achieved?Now I've looked at the implementation of chain, and I believe that the However, both the tests for reduce and the source show examples of 'Iterable' (either Yet I have a feeling that if you wire things right, you can get it done. But for the life of me I can't figure out how. GoalEssentially what I'm after is in addition to the laziness on the tranducer sequence, laziness on the chain branch (which can do one to many). By laziness I mean - one array item at a time. Like so: |
I'm pretty sure it can be achieved with transducers, but you will need to replace the |
@scott-christopher has answered my question on SO. I share the solution here: const combineWith = (fn, xs) => xf => ({
// proxy both `init` and `result` straight through
// see internal/_xfBase.js
'@@transducer/init': xf['@@transducer/init'].bind(xf),
'@@transducer/result': xf['@@transducer/result'].bind(xf),
// combine the item at each step with every element from `xs`
// using `fn`, returning early if `reduced` is ever encountered
'@@transducer/step': (acc, item) => {
for (let i = 0; i < xs.length; i++) {
acc = xf['@@transducer/step'](acc, fn(item, xs[i]))
if (acc['@@transducer/reduced']) return acc
}
return acc
}
})
const suits = ['♠', '♥', '♦', '♣']
const ranks = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'J', 'Q', 'K', 'A']
const tapLog = R.tap(console.log.bind(console, 'tapLog'))
const transducer = R.compose(
combineWith(R.concat, ranks),
tapLog,
R.take(2)
)
console.log('result', R.into([], transducer, suits)) |
The secretive laziness
As some of you know, some of us are using Ramda to compose lazy sequences. Although the library supports it, it isn't advertised anywhere, which means people like me have used lazy.js along side Ramda, although the latter alone would do.
Serendipity
Now if you're lazy, the way to surf the docs would be to search for "transducer" or "transformer".
I've been looking for months for a way to do something. But the Ramda docs said "No can do" (or more precisely, it didn't say "can do"). So I have spent 3 weeks writing an original lazy tree traversal implementation.
Then one day, by sheer accident, my eyes landed on
chain
. Not a single hint it would work, but I had to give it a go. And guess what?[REPL]
Outputs:
So it turns out
chain
works with transducers.Why is it such a big deal?
Because it allows one-to-many lazy traversal, which enables the colossal ability to lazily traverse trees and graphs, not just lists.
Here's an example, showing both breadth- and depth- first lazy graph traversal, albeit naïve.
The issue
There is no mentioning of this in the docs.
If
chain
plays nicely withtransduce
, please let it be known.The text was updated successfully, but these errors were encountered: