Few general points about your code:
(while condition &body)
form already treats &body
as an implicit progn
. There's no reason to wrap it in a progn
.
insert
accepts multiple arguments. So, you could write (insert (mapconcat ...) "\n")
instead of calling (insert ...)
followed by (newline)
.
- Traditionally, Lisp functions use
-
when the name of the function consists of multiple words, so, it would be better to call zip-list
, not zip_list
.
(let (res) ...)
is exactly the same as (let ((res)) ...)
but shorter.
(setq ...) can handle multiple assignments, they are executed in order they are written, so
(setq a b c a)will assign
bto
c. No reason to write
(setq a b) (setq c a)`.
split-string
has argument OMIT-NULLS
that controls whether empty strings are included in the results. It would be better to rely on this argument than to post-process the results.
- As mentioned in the comments, there's an easier, more idiomatic way to obtain all lines of text from the buffer:
(split-string (buffer-string) "\n")
.
Finally, unless only for the sake of an exercise in writing the zip-list
function, the transpose operation calls for something like vector, not a list. Below is a possible alternative which uses vectors to perform this operation:
(defun wvxvw/transpose-buffer ()
(interactive)
(let* ((lines (split-string (buffer-string) "\n"))
(max-length
(cl-loop for line in lines
maximize (max (length line))))
(src (cl-coerce lines 'vector))
(dst (cl-loop with matrix = (make-vector max-length nil)
with len = (length src)
for i below max-length do
(aset matrix i (make-vector len ?\ ))
finally (cl-return matrix))))
(cl-loop for i upfrom 0
for line across src do
(cl-loop for j upfrom 0
for c across line do
(aset (aref dst j) i c)))
(erase-buffer)
(cl-loop for line across dst do
(insert (cl-coerce line 'string) "\n"))))