lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


2013/3/10 199 ini <ini199.hacky@gmail.com>:
> Such as:
>   T={element1, element2, element3,}
> Why the last comma is allowed?

Note that this is allowed in C too (I tend to find out that many C/C++
programmers don't know about it).

One good reason is to allow for simpler diffs, which lead to simpler
merges. The following is a little long, and I apologize in advance,
but the matter is not a simple one to explain.

Consider the following transition from:

T = {
    element1,
    element2,
}

to:

T = {
    element1,
    element2,
    element3,
}

The unified diff of these snippets would be:

--- before
+++ after
@@ -1,4 +1,5 @@
 T = {
     element1,
     element2,
+    element3,
 }

In other words, a single line was inserted.

If I remove the last comma in both lists, the unified diff becomes:

--- before
+++ after
@@ -1,4 +1,5 @@
 T = {
     element1,
-    element2
+    element2,
+    element3
 }

This is a line removal, and two line insertions. By itself it's not a
big deal, but when there are multiple developpers working on the same
code, the first format is easier to merge. Consider a case where both
developpers add an element.

In the first format, the merge tool can see that developper 1 inserts
an element, and developper 2 insert an element:

--- before
+++ after dev 1
@@ -1,4 +1,5 @@
 T = {
     element1,
     element2,
+    element3,
 }

--- before
+++ after dev 2
@@ -1,4 +1,5 @@
 T = {
     element1,
     element2,
+    element4,
 }

It can decide to simply insert both elements (choosing the order based
on some heuristic):

--- before
+++ after devs 1 & 2
@@ -1,4 +1,6 @@
 T = {
     element1,
     element2,
+    element3,
+    element4,
 }

In the second format, an element is removed, and two are inserted.
This could be interpreted in several ways. Maybe did the developper
want to remove the last element of the list (whatever it is), and then
add "element2" and "element3" (resp. "element2" and "element4"). Or
maybe did they want to explicitly remove "element2" and the add some
elements. So this merge becomes much harder to resolve, and you either
have to use more invasive heuristics, or you throw a conflict error at
the user.

Another problem has to do with purely textual mergers. Suppose you
have these two diffs:

--- before
+++ after dev 1
@@ -1,4 +1,5 @@
 T = {
     element1,
-    element2
+    element2,
+    element3
 }

--- before
+++ after dev 2
@@ -1,4 +1,5 @@
 T = {
     element1,
-    element2
+    element2,
+    element4
 }

The merge could assume the same line has been removed in both cases,
and see the first insertion is done in both cases, so it would merge
them. But the second insertion is different, so it would keep both.
The result would be:

--- before
+++ after devs 1 & 2
@@ -1,4 +1,6 @@
 T = {
     element1,
-    element2
+    element2,
+    element3
+    element4
 }

The resulting file of that patch would be:

T = {
    element1,
    element2,
    element3
    element4
}

At a glance this looks OK, and it may even pass a quick code review
when in a hurry on a sunday evening to rush a milestone to release.
But there is a missing comma between element3 and element4.

So having all lines in a list follow the same format of
"data+separator" is a good coding convention to avoid merge problems.
And allowing a separator after the last element makes that possible. I
think it's an excellent and major reason for Lua (and C/C++) to allow
an extra comma after the last element of a table.