Hi Rudy,

I am still trying to find the right balance here.

You pointed out that the original pointer-walking version is harder to
read and maintain.  Earl had the opposite reaction and preferred the
patch version over the `cl-loop' variant.  So I tried two variants with
`pcase-lambda' (thanks for the hint!).

Version 1 keeps the explicit `while' pointer walk:

#+begin_src emacs-lisp
(setq org-columns-current-maxwidths
      (let ((widths
             (mapcar (pcase-lambda (`(,_ ,title ,width . ,_))
                       (if (wholenump width)
                           width
                         (string-width title)))
                     org-columns-current-fmt-compiled)))
        (dolist (entry cache)
          (let ((triplets (cdr entry))
                (specs org-columns-current-fmt-compiled)
                (w widths))
            (while (and triplets specs w)
              (unless (wholenump (org-columns--spec-width (car specs)))
                (setcar w
                        (max (car w)
                             (string-width (nth 2 (car triplets))))))
              (setq triplets (cdr triplets))
              (setq specs (cdr specs))
              (setq w (cdr w)))))
        (apply #'vector widths)))
#+end_src

Version 2 replaces the repeated cdr-walking with a simple `cl-loop':

#+begin_src emacs-lisp
(setq org-columns-current-maxwidths
      (let ((widths
             (mapcar (pcase-lambda (`(,_ ,title ,width . ,_))
                       (if (wholenump width)
                           width
                         (string-width title)))
                     org-columns-current-fmt-compiled)))
        (dolist (entry cache)
          (cl-loop for triplet in (cdr entry)
                   for spec-cons on org-columns-current-fmt-compiled
                   for width-cons on widths
                   unless (wholenump (nth 2 (car spec-cons)))
                   do (setcar width-cons
                              (max (car width-cons)
                                   (string-width (nth 2 triplet))))))
        (apply #'vector widths)))
#+end_src

I also ran a small benchmark:

#+begin_example
rows=50 cols=10 iterations=20000
while:   22.25 s
cl-loop: 40.21 s
ratio cl-loop/while: 1.81

rows=500 cols=10 iterations=3000
while:   32.43 s
cl-loop: 56.01 s
ratio cl-loop/while: 1.73

rows=500 cols=30 iterations=1000
while:   24.61 s
cl-loop: 28.96 s
ratio cl-loop/while: 1.18
#+end_example

So the `while' version is still faster, but the `cl-loop' version may be
a reasonable compromise if it is easier to read.

After Earl's comment, I am leaning slightly toward keeping the `while'
version, because it is faster in the benchmark.  However, I agree with
your readability concern, so I wanted to ask whether the `cl-loop'
version below looks like a better compromise to you despite the slowdown.

Best,
-- 
Slawomir Grochowski

Reply via email to