“Programs must be written for people to read, and only incidentally for machines to execute.” ― Harold Abelson, Structure and Interpretation of Computer Programs
“Programs must be written for people to read, and only incidentally for machines to execute.” ― Harold Abelson, Structure and Interpretation of Computer Programs
If I put my "Java goggles" on, the first, "untasty" snippet looks so very obviously to be the right way to do it. But...
If I put my "C goggles" on, the "clever" version from Linus looks much more direct, obvious, and better in general...much like the final example from the article author.
Linus's code here is 'clever'... but not good, simple code.
It's interesting to apply the same technique to other languages. I have to use VB.net most of the time so here are implementations of the tasteless and tasteful versions in VB (untested so there might be bugs). Even in VB the tasteful version is shorter and, I think, clearer.
Module Module1
Public Class ListEntry
Public value As String
Public [next] As ListEntry
End Class
Public Head As ListEntry
''' <summary>
''' Straight translation of Torvalds' tasteless version.
''' </summary>
''' <param name="entry"></param>
Sub RemoveListEntry(entry As ListEntry)
Dim prev As ListEntry = Nothing
Dim walk = Head
' Walk the list
While walk IsNot entry
prev = walk
walk = walk.next
End While
' Remove the entry by updating the head or the previous entry.
If prev Is Nothing Then
Head = entry.next
Else
prev.next = entry.next
End If
End Sub
''' <summary>
''' Straight translation of Torvalds' tasteful version.
''' </summary>
''' <param name="entry"></param>
Sub RemoveListEntry1(entry As ListEntry)
Dim indirect = New ListEntry
indirect.next = Head
' Walk the list looking for the thing that points at the thing that we
' want to remove.
While indirect.next IsNot entry
indirect = indirect.next
End While
' ... and just remove it.
indirect.next = entry.next
End Sub
End Module'Simplify so a fool can understand your code, and you will have fools editing it.'
'Modern' 'pascals' were different.
So not identical but still simpler than the tasteless version.
I thought that this was such a fundamental idea that it should be on Rosetta Code but the page for it at http://rosettacode.org/wiki/Singly-linked_list/Element_remov... is empty.
Perhaps we should all rush over there and fill it in. :-)
Edit: See entry on RC at http://rosettacode.org/wiki/Singly-linked_list/Element_remov...
One argument is that code should be written so that junior or average (or even below average) developers can be put to work on it. Another view is that part of a junior developer's learning experience ought to include not shielding him from alleged complexity or "clever" constructs, because sometimes they really are better or even unavoidable.
Cleverness for its own sake is one thing to avoid, but I think that's almost too subjective a standard to use.
And I seriously fail to see the 'for its own sake' here. This cleverness reduces the number of moving parts, does the 'dont repeat yourself' and thus reduces ways modifications of the code could break it due to overseeing a case.
I just shuddered to think how this would be done in java - with a LinkUpdater interface, and a RootLinkUpdater and ElementLinkUpdater, and one instantiation per iteration, and suddenly we have a lot of code around to keep the active code's function simple - to a point where it is completely pointless because of adding a lot of machinery. (And java does collections differently anyway.)
When I look back on my career, often when I've said something is "clever for its own sake" was only clever because of a lack of understanding on my part, and rarely for its own sake, outside of toys and obscurity competition where such cleverness is the point.