[transducers] Transducers crash when source is an empty string
See original GitHub issueMost transducers take a source sequence as a final argument. Since strings are iterable, so you can do this:
[...tx.filter(x => true, "abc")]
"abc"
However, if you provide an empty string, they will crash:
[...tx.filter(x => true, "")]
TypeError: tx.filter(...) is not iterable
This is obviously because the transducer functions do a truthiness test on their final argument to determine whether a source was provided:
export function map<A, B>(fn: Fn<A, B>): Transducer<A, B>;
export function map<A, B>(fn: Fn<A, B>, src: Iterable<A>): IterableIterator<B>;
export function map<A, B>(fn: Fn<A, B>, src?: Iterable<A>): any {
return src
? iterator1(map(fn), src)
: (rfn: Reducer<any, B>) => {
const r = rfn[2];
return compR(rfn, (acc, x: A) => r(acc, fn(x)));
};
}
This could be corrected by replacing src
with isIterable(src)
(using @thi.ng/checks
). This would incur the additional work of looking up Symbol.iterator
, but it would seem to be more correct. I can’t think of a case where this would be a breaking change (i.e. values for src
that work now but are not iterable by that test).
@postspectacular I’m willing to PR if you think this is actionable. I understand there’s a lot of branch work going on, so whatever you think best.
A workaround for the time being is to wrap the string argument in [...s]
.
Issue Analytics
- State:
- Created 4 years ago
- Comments:14 (14 by maintainers)
Top GitHub Comments
Thank you for the in-depth analysis, @gavinpc-mindgrub! In this case I’d opt (like I guess you do too) for consistency, even if it means breaking the current behavior for top-level strings (incl. empty ones).
So I’d say we treat top-level strings as atoms (unflattenable, just like nested strings) and update the body of
flattenWith
to something like:With that change we get:
@gavinpc-mindgrub no pressure pls! take your time!