3
\$\begingroup\$

I have written a few classical Python functions in JavaScript. I would appreciate any kind of feedback. The main goal is to learn about JavaScript. For example errors, improvements or existing JavaScript functions that I missed. Additionally, challenges that would be interesting to tackle next would be appreciated.

// Lets start with a simple one: 
function list(e){ 
  return Array.from(e);
}


function* zip(...iterables){
   const iterators = iterables.map(it => iter(it));
   while(true){
      const items = iterators.map(it => it.next());
      if (items.some(item => item.done)){
         return;
      }
      yield items.map(item => item.value);
  }
}

function* map(func, iterable){
  for (let elem of iterable){
    yield func(elem);
  }
}

function* enumerate(iterable, start=0){
  let i = start;
  for (let elem of iterable){
    yield [i++, elem];
  }
}

function* iter(object, sentinel){
  if (!sentinel){
    yield* object;
    return;
  }
  while (true) {
    if (typeof object !== "function"){
      throw TypeError("iter(object, sentinel): object must be a function")
    }
    result = object();
    if (result === sentinel){
      return;
    }
    yield result;
  }
}

function* repeat(object, times){
  for (let i = 0; i < times; i += 1) yield object;
}

function* range(start, end=undefined, step=1) {
  if(end === undefined){
    end = start;
    start = 0;
  }
  for (let i = start; i < end; i += step){
    yield i;
  }
}

function* cycle(iterable){
  saved = [];
  for (const e of iterable){
    yield e
    saved.push(e);
  }
  while (true) yield* saved;
}

function* islice(iterable, start, end){
  if (!end){
    end = start;
    start = 0;
  }
  dropfirsts(iterable, start);
  yield* firsts(iterable, end-start);
}

function dropfirsts(iterable, n){
  for (let i of range(n)){ 
    if (iterable.next().done) return;
  }
}

function* firsts(iterable, n){
  for (let j of range(n)){
    const item = iterable.next();
    if (item.done) return;
    yield item.value;
  }
}

Here are a few examples of how to use it. These are likely not the best.

console.log("Repeating the same value with repeat():")
console.log("\t", list(repeat("x", 5)));

console.log("Pairs of consecutive items from a list using zip():");
const l = [1,2,3,4];
const liter = iter(l);
const literNext = iter(l);
literNext.next();
for (const [x, y] of zip(liter, literNext)) {
  console.log("\t", x, y);
}

console.log("Iterator over a callable (with sentinel):");
function f(){
  let count = 0;
  return () => count+=1;
}
for (const x of iter(f(), 5)){
  console.log("\t", x);
}

console.log("Pairing two lists of distinct size with zip():");
for (const [x, y] of zip([1, 2, 3], ["a", "b"])) {
  console.log("\t", x, y);
}

console.log("Building two lists from a list of pairs using zip():");
const pairList = [[1,2], [3,4], [5,6], [7,8]];
for (const X of zip(...pairList)) {
  console.log("\t", X);
}

console.log("Time two table using zip() and range():");
for (let [i,j] of zip(range(5), range(0, 10, 2))){
  console.log("\t", `${i} x 2 = ${j}`);
}

console.log("Enumerate letters from the alphabet with enumerate():");
for (let [i, e] of enumerate(["a", "b", "c"], 1)){
  console.log("\t", e, i);
} 

console.log("Convert an iterable to an array using list():");
const rangeLen = 5;
console.log("\t", `list(range(${rangeLen})) = `, list(range(rangeLen)));

const squares = list(map(i => i*i, range(5))).join(',');
console.log("Map an iterator using map():");
console.log("\t", `squares = ${squares}`);


const size = 3;
const cycleThrough = [1, 2];
console.log(`Cycle (firsts ${size} elements) of [${cycleThrough}] using cycle():`);
let i = 0;
for (const x of cycle(cycleThrough)){
  i += 1;
  if (i > size) break;
  console.log("\t", x);
}

console.log(`Same using cycle() and islice():`);
for (const x of islice(cycle(cycleThrough), size)){
  console.log("\t", x);
}

const start = 1;
console.log(`Same but starting at element ${start}:`);
for (const x of islice(cycle(cycleThrough), start, size+start)){
  console.log("\t", x);
}
\$\endgroup\$
0

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.