0

Question: Is it possible to compose two generators into one generator like you would with compose?

function* type(vals) {
  for(const v of vals) {
    yield v;
  }
}

const bool = type([true, false]);
const str = type([
  '',
  undefined,
  'Lorem',
  'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
  ''
]);

const composeGenerator = () => {/*???*/};  
const input = composeGenerator(bool,str);
console.log(input, 'yes');

for (const i of bool) {
  console.log(i); // true, false
}

for (const i of str) {
  console.log(i); // '',  undefined,  'Lorem',  'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',  ''
}

for (const i of input) {
  console.log(i); // '',  undefined,  'Lorem',  'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',  '', true, false
}
Armeen Moon
  • 18,061
  • 35
  • 120
  • 233
  • Also your expected output is in the order of `[...str, ...bool]` but your parameters are in the order `bool, str`. Was that intentional? – Patrick Roberts Jul 19 '19 at 04:55
  • @PatrickRoberts either order is fine... compose is right to let sometimes. but Im indifferent – Armeen Moon Jul 19 '19 at 04:56
  • In function composition, you pass the result of one function as an argument to the other. Your generator functions do not take any arguments though, so this doesn't make any sense? Your desired output (the `input` iterable) looks much more like a simple **concatenation**. – Bergi Jul 19 '19 at 15:51
  • You can simply concatenate generators or any iterables with [iter-ops](https://github.com/vitaly-t/iter-ops) library ;) – vitaly-t Dec 14 '21 at 11:33

2 Answers2

1

Your type function can actually be shortened, first of all. Secondly, here's one possible implementation of your composeGenerator from left to right:

function * type (iterable) {
  yield * iterable;
}

const bool = type([true, false]);
const str = type([
  '',
  undefined,
  'Lorem',
  'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
  ''
]);

function * composeGenerator (...iterables) {
  for (const iterable of iterables) yield * iterable;
}

const input = composeGenerator(str, bool);

for (const i of input) {
  console.log(i);
}
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • if you made bool and str functions like const bool = () => type ([true, false]) they could be excuted again right? – Armeen Moon Jul 19 '19 at 05:10
  • 1
    @MatthewHarwood no, that's not right. If you want to unaccept my answer go ahead, but doing that is not trivial. You'd have to modify the objects you accepted as input, which could lead to complicated and unexpected behavior. – Patrick Roberts Jul 19 '19 at 05:12
  • https://gist.github.com/matthewharwood/b722988116afc8eb79a8321a3e940eee no it did work but maybe I didn't explain it @PatrickRoberts – Armeen Moon Jul 19 '19 at 05:22
  • @MatthewHarwood actually I think I misread your first comment. Should I edit my answer to address how you'd be able to re-use your curried functions? – Patrick Roberts Jul 19 '19 at 05:23
  • Yeah go ahead lets do that! also if your down round 2 is here https://stackoverflow.com/questions/57105848/write-a-fn-loop-that-iterate-over-a-generator-that-has-inner-generators – Armeen Moon Jul 19 '19 at 05:24
  • @MatthewHarwood Ah nevermind, I guess I don't need to edit. I need to work on reading comments better apparently. Yes it does work the way you expected it to when encapsulating in higher order functions. – Patrick Roberts Jul 19 '19 at 05:30
0

We iterate over all generators until they yield a value

function* type(vals) {
  for(const v of vals) {
    yield v;
  }
}

const bool = type([true, false]);
const str = type([
  '',
  undefined,
  'Lorem',
  'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
  ''
]);

function *composeGenerator(...iterators) {
  for (const iterator of iterators) {
    for (const value of iterator ) {
      yield value;
    }
  }
}

const input = composeGenerator(bool,str);

for (const i of input) {
  console.log(i);
}
Sid Vishnoi
  • 1,250
  • 1
  • 16
  • 27
  • The question showed that `bool` and `str` were iterated prior to iterating `input`. This wouldn't work in the example code provided. – Patrick Roberts Jul 19 '19 at 05:02
  • I think that was shown for demonstrative purposes only. – Sid Vishnoi Jul 19 '19 at 05:05
  • One would have to reset the iterators if they want to iterate over them again (https://stackoverflow.com/questions/23848113/is-it-possible-to-reset-an-ecmascript-6-generator-to-its-initial-state) (and the question is here about composition) – Sid Vishnoi Jul 19 '19 at 05:06