okamsn / loopy

A better looping and iteration macro for Emacs.
GNU General Public License v3.0
23 stars 3 forks source link

some iter clauses that don't support arbitrary nesting #62

Open Luis-Henriquez-Perez opened 3 years ago

Luis-Henriquez-Perez commented 3 years ago

Some clauses in iter don't accept arbitrary clauses such as before-do.

For example, I would expect to be able to use collect within initially-do. But iter does not check in before-do (and I'm assuming it also does not do so for similar clauses like after-do either). I think it should.

(cl-defun defun%parse-hook (init _ hooks &key depth append local)
  (let-alist init
    (iter (with (orig-name (format "xl--%s-hook" .name)))
          ;; LOOK HERE.
      (initially (collect `(cl-defun ,orig-name ,.args ,.docstring ,@.body)))
      (each hook hooks)
      (expr hook-fn (xl-symbol-intern hook '& .name))
      (collect `(defalias ',hook-fn ',orig-name))
      (collect `(add-hook ',hook #',hook-fn ,(or append depth) ,local)))))
okamsn commented 3 years ago

Accumulation variables need to be complete before after-do runs, so it wouldn't work to allow collect in them. For example, updates to accumulation variables, such as coercing their type or correcting the order of a list made in reverse, need to happen before code in after-do could try to access them.

It would only work in before-do, and I think it less expected to allow it in before-do without also allowing it in after-do. Neither cl-loop or iterate allow this, as far as I can tell.

Besides, accumulating into a variable in before-do can also just be done by setting the variable in with, though this might involve knowing more about how the macro works.

(loopy (with (loopy-result '(initial-value)))
       (nums i 1 3)
       (collect i))

;; Currently expands to:
;; => (initial-value 1 2 3)
(let* ((loopy-result '(initial-value)))
  (let* ((loopy-result-last-link-129 (last loopy-result)))
    (let* ((i 1)
           (nums-increment127 1)
           (nums-end128 3))
      (let ((loopy-first-iteration t))
        (progn
          (while (<= i nums-end128)
            (cond (loopy-result-last-link-129
                   (setcdr loopy-result-last-link-129
                           (list i))
                   (setq loopy-result-last-link-129
                         (cdr loopy-result-last-link-129)))
                  (loopy-result
                   (setq loopy-result-last-link-129 (last loopy-result))
                   (setcdr loopy-result-last-link-129 (list i))
                   (setq loopy-result-last-link-129
                         (cdr loopy-result-last-link-129)))
                  (t
                   (setq loopy-result (list i)
                         loopy-result-last-link-129 loopy-result)))
            (setq i (+ i nums-increment127))
            (setq loopy-first-iteration nil))
          loopy-result)))))

So, while this would be nice to have, it currently would only work for before-do, where it isn't particularly needed anyway. I think this issue should stay open, but I'm not expecting things to change without majorly complicating how code is generated.