Live data from Hacker News

Linus Torvalds' good taste argument for linked lists, explained

github.com

21–30 of 339 posts

Re: Linus Torvalds' good taste argument for linked lists, explained

#21
This seems like the classic argument of whether approaches like Duff's Device[1] are a good implementation idea.

I would offer that there is no shame in doing something a bit more advanced, as long as there are test cases and documentation proportional to the advanced nature of the technique available.

[1] https://en.m.wikipedia.org/wiki/Duff's_device

Re: Linus Torvalds' good taste argument for linked lists, explained

#22
The second version seems more elegant but will scare non-C people away with all those pointers ;-)

What I do not understand is why one should use an "IntList" struct in the first place? As the explanation of the second method suggests, a List is the same thing as a pointer to its first element, so why not do this?:

typedef struct IntListItem* IntList;

Also, could it be that both methods fail terribly (infinite loops?) when they are given wrong input such as elements not in the list at all?

Re: Linus Torvalds' good taste argument for linked lists, explained

#23

I understand the general point (and value) of reframing the problem or the solution in a way that removes special cases ... but in this case I would actually prefer the first solution over the second. The second solutions reminds me of the old-school perl culture, and JavaScript culture, where 'cleverness' (which always manifests itself as terseness as if lines of code were expensive), takes precedence over maintaina…

I totally agree, it’s about proving you’re clever rather than communicating ideas. Maybe for something hard like Linux kernel development this is a good thing but in most cases it just leads to messy code that people can’t understand or follow.

Re: Linus Torvalds' good taste argument for linked lists, explained

#24

I understand the general point (and value) of reframing the problem or the solution in a way that removes special cases ... but in this case I would actually prefer the first solution over the second. The second solutions reminds me of the old-school perl culture, and JavaScript culture, where 'cleverness' (which always manifests itself as terseness as if lines of code were expensive), takes precedence over maintaina…

I totally agree, it’s about proving you’re clever rather than communicating ideas. Maybe for something hard like Linux kernel development this is a good thing but in most cases it just leads to messy code that people can’t understand or follow.

While there certainly are such cases, I think here it’s just about being proficient in a language. Pointers, referencing and dereferencing are the bread and butter of any C code, and applying them in a way to reduce complexity is certainly something to strive for - if this isn’t readable then I’d argue the reader shouldn’t be touching the codebase anyways.

Re: Linus Torvalds' good taste argument for linked lists, explained

#25
Let's draw a list

  IntListItem -> IntListItem -> IntListItem
and then draw the position of the list head:

  IntList -> IntListItem -> IntListItem -> IntListItem
You can see that the if-branch in the cs101 answer comes because there is a ('virtual') element of the list (the IntList head) that is different from the other elements of the list.

If we were to make them the same (C# code):

  interface IListItem 
  {
     IntListItem Next {get;set;}
  }

  class IntListItem : IListItem
  {
     int Value {get; set;}
     IntListItem Next {get; set;}
  }

  class IntList : IListItem
  {
     IntListItem Head {get; set;}
     IntListItem Next 
     {
        get { return Head; }
        set { Head = value; } 
     }
  }
then our cs101 code simplifies itself, folding into a prettier algorithm:

  void remove_cs102(IntList l, IntListItem target)
  {
     IListItem p = (IListItem) l;
     while (p.Next != target) 
     { 
        p = (IListItem) p.Next;
     }
 
     p.Next = p.Next.Next;
  }
the use of indirect pointers was masking the real issue: some algorithms look better if you add a virtual head (or a virtual tail) to your linked list. Emphasis on look though -- they work almost the same.

Re: Linus Torvalds' good taste argument for linked lists, explained

#26

I understand the general point (and value) of reframing the problem or the solution in a way that removes special cases ... but in this case I would actually prefer the first solution over the second. The second solutions reminds me of the old-school perl culture, and JavaScript culture, where 'cleverness' (which always manifests itself as terseness as if lines of code were expensive), takes precedence over maintaina…

Looking at the code there are not just fewer lines, but fewer conditionals too. It's much simpler to read and understand. I got it at a glance, whereas I skimmed the typical approach and would still need to go over it more carefully to be sure it is correct.

I think Linus is correct on this one.

Re: Linus Torvalds' good taste argument for linked lists, explained

#27
post #22

The second version seems more elegant but will scare non-C people away with all those pointers ;-) What I do not understand is why one should use an "IntList" struct in the first place? As the explanation of the second method suggests, a List is the same thing as a pointer to its first element, so why not do this?: typedef struct IntListItem* IntList; Also, could it be that both methods fail terribly (infinite loops?…

> Also, could it be that both methods fail terribly (infinite loops?) when they are given wrong input such as elements not in the list at all?

You could just say "has undefined behavior unless target is an element of the list".

Whatever your choice though - this is slide code. It should be obvious that it's not production ready.

Re: Linus Torvalds' good taste argument for linked lists, explained

#28

I understand the general point (and value) of reframing the problem or the solution in a way that removes special cases ... but in this case I would actually prefer the first solution over the second. The second solutions reminds me of the old-school perl culture, and JavaScript culture, where 'cleverness' (which always manifests itself as terseness as if lines of code were expensive), takes precedence over maintaina…

> "which always manifests itself as terseness as if lines of code were expensive)"

They are expensive! Your code maintained years in the future, every developer has to potentially read every damn line.

The alternative to "clever" code isn't Java and FactoryFactoryFactories, it's short clear code, which is different from short codegolfed code. The main difference is nicely designed libraries and abstractions.

Re: Linus Torvalds' good taste argument for linked lists, explained

#29
I think what's missing in the mental model of the elegant solution is, that the IntList-pointer does not point to a complete list or an element of the list, but to a tail of some list (that might be the complete list). This explains why the head is not really a special case, as it points to the tail that is complete. And you can just exchange a tail.

So I think the image with the blue boxes is misleading and it should be

->[4->[12->[3->[6->[2->[]]]]]]

It is now obvious that you can always point -> to a different [...]

And as it turns out, that is basically the Cons/Nil view of a list from functional programming or lisp, if you're so inclined. And in those languages you would pattern match on the constructor once and do the tail-recursive call.

Re: Linus Torvalds' good taste argument for linked lists, explained

#30
Maybe slightly off topic, but..

I don't think this is really about taste. It's about "common ground" between programmers. If you've seen and used the second pattern many times before, it becomes part of your vocabulary. You're then able to express yourself more succinctly. It is then obviously a better solution to you.

If you see another programmer use the same pattern, it is common ground between you, and you like it. As long as every or most programmers on the team share the same common ground, you are more effective for using it. If you don't share it, you're less effective.

Everyone here commenting that they like the first solution better probably doesn't share the necessary common ground with Linus.

The big question is: what common grounds should you expect when writing your code?

Post reply on HN