Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call join() on a generator in JS

In Python, you can call the string.join() method on any iterable, like so:

",".join(some_iterable)

The argument may be a list, generator, or any other object as long as it is iterable.

Playing around with ES6, I couldn't find a way to do so without having to create an array first, I had to do something like this:

function *myGenerator() { ... }
let output = [...myGenerator()].join(",");

I know that join() is an Array.prototype method. Is it possible for me to call join() or some equivalent to concatenate the values generated by myGenerator without having to create an intermediate array, like the python example above?

like image 481
nasser-sh Avatar asked Jul 09 '18 22:07

nasser-sh


People also ask

How do you call a function from a normal generator?

Calling a generator function inside another to generate a function: we can call a generator function inside another generator function by using the yield * operator (or statement). Example 3: In this example, we call a generator function inside another generator function using the yield * statement.

How do you end a generator function?

To finish the execution of the generator function, we can use the return statement. Returned value will be used to set the value property of the object returned by the generator.

How do you define a generator function in JavaScript?

Generator functions are written using the function* syntax. When called, generator functions do not initially execute their code. Instead, they return a special type of iterator, called a Generator.

Which is the correct syntax for a generator?

To create a generator, we need a special syntax construct: function* , so-called “generator function”. Generator functions behave differently from regular ones. When such function is called, it doesn't run its code. Instead it returns a special object, called “generator object”, to manage the execution.


1 Answers

The comments above answer your question pretty well. However, I was curious about @jonrsharpe's comment about generating intermediate strings and was wondering how that actually affected performance. So I put a join method on the prototype of a generator and tested it.

Here's the join() code:

function* nGen(start, stop) {
  while (start < stop) {
    yield start
    start++
  }
}

nGen.prototype.join = function(sep) {
  let res = this.next().value
  for (let v = this.next(); !v.done; v = this.next()) {
    res += sep + v.value
  }
  return res
}


let g = nGen(2, 20)

console.log(g.join(','))

The original jsPerf tests in Safari and Chrome showed this working faster than the very common idiom: [...g].join(','). In a JSBench test in 2022, results were inconsistent between Chrome, Firefox, and Edge, but this method is now slower than [...g].join(',') and/or a for loop.

I am far from a master of writing jsPerf/JSBench tests, so maybe I'm screwing something up or misinterpreting the result. But if you're interested: https://jsbench.me/zlkz8tm6vw/1

like image 162
Mark Avatar answered Oct 14 '22 18:10

Mark