On Tue, Apr 9, 2013 at 5:31 AM, Nick Dokos <ndo...@gmail.com> wrote:
> You can turn on formula debugging with C-c { and then you'd
> see that in Pancho's case, the list is ("") i.e. a list containing the
> empty string - a list of length 1. That might qualify as a bug (or not)

This issue is part of some old bugs that I discovered end of 2012. It
seems like my patch from then
http://orgmode.org/w/org-mode.git?p=org-mode.git;a=commitdiff;h=764315
resolved it only partially and I missed the case of a range with only
empty fields, although I tested and approved it in my ERTs... The
attached patch corrects.

It is worth a small compatibility change: For a range with only empty
fields it is now possible and necessary to choose different behaviors
of vmean by adding the format specifiers E and/or N.

Michael
From 758414846936936f4e985fdb4de82eb7c95f163f Mon Sep 17 00:00:00 2001
From: Michael Brand <michael.ch.br...@gmail.com>
Date: Tue, 9 Apr 2013 14:35:21 +0200
Subject: [PATCH] org-table.el: Fix range len bugs for empty ranges

(org-table-make-reference): A range with only empty fields should lead
to length 0.
* testing/lisp/test-org-table.el: Adapt expected for several
ert-deftest.

The range len bugs may lead to wrong calculations for range references
with empty fields when the range len is relevant.  Affects typically
Calc vmean on simple range and without format specifier EN.  Also
Lisp with e. g. `length' on simple range or with L.

It is worth a small compatibility change: For a range with only empty
fields it is now possible and necessary to choose different behaviors
of vmean by adding the format specifiers E and/or N.

This is a follow-up of commit
764315b3fce26de59189b957a8049e299209043a.
---
 lisp/org-table.el              |  7 +++--
 testing/lisp/test-org-table.el | 60 ++++++++++++++++++++++++++----------------
 2 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/lisp/org-table.el b/lisp/org-table.el
index bdf4ad8..7122c87 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -2929,7 +2929,10 @@ list, 'literal is for the format specifier L."
       (if lispp
          (if (eq lispp 'literal)
              elements
-           (prin1-to-string (if numbers (string-to-number elements) elements)))
+           (if (and (eq elements "") (not keep-empty))
+               ""
+             (prin1-to-string
+              (if numbers (string-to-number elements) elements))))
        (if (string-match "\\S-" elements)
            (progn
              (when numbers (setq elements (number-to-string
@@ -2942,7 +2945,7 @@ list, 'literal is for the format specifier L."
            (delq nil
                  (mapcar (lambda (x) (if (string-match "\\S-" x) x nil))
                          elements))))
-    (setq elements (or elements '("")))
+    (setq elements (or elements '()))  ; if delq returns nil then we need '()
     (if lispp
        (mapconcat
         (lambda (x)
diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el
index 01adf52..2dd5f38 100644
--- a/testing/lisp/test-org-table.el
+++ b/testing/lisp/test-org-table.el
@@ -339,7 +339,7 @@ reference (with row).  No format specifier."
 | 0 | 1 | 0 | #ERROR | #ERROR | #ERROR | 2 | 2 |
 | z | 1 | z | #ERROR | #ERROR | #ERROR | 2 | 2 |
 |   | 1 |   | #ERROR | #ERROR | #ERROR | 1 | 1 |
-|   |   |   | #ERROR | #ERROR | #ERROR | 1 | 1 |
+|   |   |   | #ERROR | 0      | 0      | 0 | 0 |
 "
      1 lisp)
     (org-test-table-target-expect
@@ -348,7 +348,7 @@ reference (with row).  No format specifier."
 | 0 | 1 | 0 |     1 |     1 |     1 | 2 | 2 |
 | z | 1 | z | z + 1 | z + 1 | z + 1 | 2 | 2 |
 |   | 1 | 0 |     1 |     1 |     1 | 1 | 1 |
-|   |   | 0 |     0 |     0 |     0 | 1 | 1 |
+|   |   | 0 |     0 |     0 |     0 | 0 | 0 |
 "
      1 calc)
     (org-test-table-target-expect
@@ -381,7 +381,7 @@ reference (with row).  Format specifier N."
 | 0 | 1 | 0 | 1 | 1 | 1 | 2 | 2 |
 | z | 1 | 0 | 1 | 1 | 1 | 2 | 2 |
 |   | 1 | 0 | 1 | 1 | 1 | 1 | 1 |
-|   |   | 0 | 0 | 0 | 0 | 1 | 1 |
+|   |   | 0 | 0 | 0 | 0 | 0 | 0 |
 "
      1 lisp calc)
     (org-test-table-target-expect
@@ -455,20 +455,34 @@ reference (with row).  Format specifier N."
   ;; Empty fields in simple and complex range reference: Suppress them
   ;; ($5 and $6) or keep them and use 0 ($7 and $8)
 
-  (org-test-table-target-expect
-   "\n|   |   | 5 | 7 | replace | replace | replace | replace |\n"
-   "\n|   |   | 5 | 7 | 6 | 6 | 3 | 3 |\n"
-   1
-   ;; Calc formula
-   (concat "#+TBLFM: "
-          "$5 = vmean($1..$4)     :: $6 = vmean(@0$1..@0$4) :: "
-          "$7 = vmean($1..$4); EN :: $8 = vmean(@0$1..@0$4); EN")
-   ;; Lisp formula
-   (concat "#+TBLFM: "
-          "$5 = '(/ (+   $1..$4  ) (length '(  $1..$4  )));  N :: "
-          "$6 = '(/ (+ @0$1..@0$4) (length '(@0$1..@0$4)));  N :: "
-          "$7 = '(/ (+   $1..$4  ) (length '(  $1..$4  ))); EN :: "
-          "$8 = '(/ (+ @0$1..@0$4) (length '(@0$1..@0$4))); EN"))
+  (let ((calc (concat
+              "#+TBLFM: "
+              "$5 = vmean($1..$4)     :: "
+              "$6 = vmean(@0$1..@0$4) :: "
+              "$7 = vmean($1..$4); EN :: "
+              "$8 = vmean(@0$1..@0$4); EN"))
+       (lisp (concat
+              "#+TBLFM: "
+              "$5 = '(/ (+   $1..$4  ) (length '(  $1..$4  )));  N :: "
+              "$6 = '(/ (+ @0$1..@0$4) (length '(@0$1..@0$4)));  N :: "
+              "$7 = '(/ (+   $1..$4  ) (length '(  $1..$4  ))); EN :: "
+              "$8 = '(/ (+ @0$1..@0$4) (length '(@0$1..@0$4))); EN")))
+    (org-test-table-target-expect
+     "\n|   |   | 5 | 7 | replace | replace | replace | replace |\n"
+     "\n|   |   | 5 | 7 | 6 | 6 | 3 | 3 |\n"
+     1 calc lisp)
+
+    ;; The mean value of a range with only empty fields is not defined
+    (let ((target
+          "\n|   |   |   |   | replace | replace | replace | replace |\n"))
+      (org-test-table-target-expect
+       target
+       "\n|   |   |   |   | vmean([]) | vmean([]) | 0 | 0 |\n"
+       1 calc)
+      (org-test-table-target-expect
+       target
+       "\n|   |   |   |   | #ERROR | #ERROR | 0 | 0 |\n"
+       1 lisp)))
 
   ;; Test if one field is empty, else do a calculation
   (org-test-table-target-expect
@@ -667,11 +681,11 @@ reference (with row).  Format specifier N."
   ;; For Lisp formula
   (should (equal "\"0\""       (f   "0"         nil nil t)))
   (should (equal "\"z\""       (f   "z"         nil nil t)))
-  (should (equal  "\"\""       (f   ""          nil nil t)))
+  (should (equal   ""          (f   ""          nil nil t)))
   (should (equal "\"0\" \"1\"" (f '("0"    "1") nil nil t)))
   (should (equal "\"z\" \"1\"" (f '("z"    "1") nil nil t)))
   (should (equal       "\"1\"" (f '(""     "1") nil nil t)))
-  (should (equal    "\"\""     (f '(""     "" ) nil nil t)))
+  (should (equal      ""       (f '(""     "" ) nil nil t)))
   ;; For Calc formula
   (should (equal  "(0)"        (f   "0"         nil nil nil)))
   (should (equal  "(z)"        (f   "z"         nil nil nil)))
@@ -679,7 +693,7 @@ reference (with row).  Format specifier N."
   (should (equal  "[0,1]"      (f '("0"    "1") nil nil nil)))
   (should (equal  "[z,1]"      (f '("z"    "1") nil nil nil)))
   (should (equal    "[1]"      (f '(""     "1") nil nil nil)))
-  (should (equal   "[0]"       (f '(""     "" ) nil nil nil)))
+  (should (equal   "[]"        (f '(""     "" ) nil nil nil)))
   ;; For Calc formula, special numbers
   (should (equal  "(nan)"      (f    "nan"      nil nil nil)))
   (should (equal "(uinf)"      (f   "uinf"      nil nil nil)))
@@ -695,11 +709,11 @@ reference (with row).  Format specifier N."
   ;; For Lisp formula
   (should (equal  "0"    (f   "0"         nil t t)))
   (should (equal  "0"    (f   "z"         nil t t)))
-  (should (equal  "0"    (f   ""          nil t t)))
+  (should (equal  ""     (f   ""          nil t t)))
   (should (equal  "0 1"  (f '("0"    "1") nil t t)))
   (should (equal  "0 1"  (f '("z"    "1") nil t t)))
   (should (equal    "1"  (f '(""     "1") nil t t)))
-  (should (equal   "0"   (f '(""     "" ) nil t t)))
+  (should (equal   ""    (f '(""     "" ) nil t t)))
   ;; For Calc formula
   (should (equal "(0)"   (f   "0"         nil t nil)))
   (should (equal "(0)"   (f   "z"         nil t nil)))
@@ -707,7 +721,7 @@ reference (with row).  Format specifier N."
   (should (equal "[0,1]" (f '("0"    "1") nil t nil)))
   (should (equal "[0,1]" (f '("z"    "1") nil t nil)))
   (should (equal   "[1]" (f '(""     "1") nil t nil)))
-  (should (equal  "[0]"  (f '(""     "" ) nil t nil)))
+  (should (equal  "[]"   (f '(""     "" ) nil t nil)))
   ;; For Calc formula, special numbers
   (should (equal "(0)"   (f    "nan"      nil t nil)))
   (should (equal "(0)"   (f   "uinf"      nil t nil)))
-- 
1.8.1.2

Reply via email to