4
\$\begingroup\$

This is an attempt to write a function link that creates a linked list from an array:

function link(list) {
    let next = tail = null;

    for(let i = list.length-1; i >= 0; i--) {        
      const value = list[i];        
      next = { value, next };
    }

    let cursor = head = next;

    function* iterator() {
      while(cursor.next) {
        yield cursor;
        cursor = cursor.next
      }
      yield cursor;
    }

    return {
      [Symbol.iterator]: iterator,
      head,
      tail,
    };
}

console.log(...link([1,2,3,4]));

The iterator maintains a cursor to remember its position in the iteration.

This feels wrong and brittle.

Is it?

If so, how should the iterator be implemented here.

\$\endgroup\$
8
  • \$\begingroup\$ the structure youre generating feels wrong to me. i feel like you should get the code that consumes this structure reviewed and figure out a way to use a flat array instead. \$\endgroup\$ Commented Jul 6, 2017 at 14:47
  • \$\begingroup\$ I am walking from the right of the supplied list creating objects (list elements). Each time I create a list element I hold a reference to it and use that when populating the next property of the "previous" element. Can you explain which aspect feels wrong to you? \$\endgroup\$
    – 52d6c6af
    Commented Jul 6, 2017 at 14:52
  • \$\begingroup\$ The structure you're building doesn't really add any value to the data. You're not really doing anything here except re-arranging data. Your final structure will require more than a simple loop to interate and there's no easy way to get a length from it without referring to the original object. Unless you require this structure for a web service or something the whole thing just feels unintuitive to me. Just my 0.02. \$\endgroup\$ Commented Jul 6, 2017 at 15:12
  • \$\begingroup\$ It's a linked list (albeit without insert, delete etc). Is it not? \$\endgroup\$
    – 52d6c6af
    Commented Jul 6, 2017 at 15:35
  • \$\begingroup\$ What it is is more complicated than necessary. The question I'm asking is why is it a linked list? You may have a perfectly legitimate reason for doing what you're doing I just can't see the point on my end. Carry on.. \$\endgroup\$ Commented Jul 6, 2017 at 16:05

2 Answers 2

3
\$\begingroup\$

How about the following recursive approach

function link(list) {
    if(!list.length)
        return [];

    let [car, ...cdr] = list;
    return {
        car,
        cdr: link(cdr),
        [Symbol.iterator]: function*() {
            yield this;
            yield *this.cdr;
        }
    }
}

ls = link([1, 2, 3, 4])

for (let t of ls)
    console.log(t.car)

\$\endgroup\$
1
  • \$\begingroup\$ I think this implementation is fantastic. \$\endgroup\$
    – 52d6c6af
    Commented Jul 11, 2017 at 8:56
0
\$\begingroup\$

The number one problem with the code as originally written was that cursor was maintained at instance- rather than iterator-invocation level.

This is what "felt wrong" to me, although I could not articulate it at the time.

The following updated implementation moves the position of the cursor variable to solve this issue.

function link(list) {
    let next = tail = null;

    for(let i = list.length-1; i >= 0; i--) {        
      const value = list[i];        
      next = { value, next };
    }

    function* iterator() {
      let cursor = this.head;
      while(cursor.next) {
        yield cursor;
        cursor = cursor.next
      }
      yield cursor;
    }

    return {
      [Symbol.iterator]: iterator,
      head: next,
      tail,
    };
}

var ll = link([1,2,3,4]);
console.log(...ll);
console.log(...ll);

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.