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.

200_success
146k22 gold badges190 silver badges479 bronze badges
asked Jul 6, 2017 at 11:49
\$\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\$ 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\$ 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)

answered Jul 6, 2017 at 11:59
\$\endgroup\$
1
  • \$\begingroup\$ I think this implementation is fantastic. \$\endgroup\$ 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);

answered Jul 7, 2017 at 9:34
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.