Skip to content

Instantly share code, notes, and snippets.

@grzs
Last active November 25, 2023 10:04
Show Gist options
  • Save grzs/f8bc39a8bec813d6f94402a7370cf667 to your computer and use it in GitHub Desktop.
Save grzs/f8bc39a8bec813d6f94402a7370cf667 to your computer and use it in GitHub Desktop.
Emacs Lisp for loop macro
(defmacro for (loopvar in listvar &rest body)
"Execute a simple for loop: (for x in '(1 2 5) (print x))."
;; syntax checking
(if (symbolp loopvar) t
(error (format "Syntax error 'for %s<- ...': LOOPVAR has to be a symbol" loopvar)))
(if (equal (symbol-name in) "in") t
(error (format "Syntax error 'for %s %s<- ...'" loopvar (symbol-name in))))
;; unintered symbols for local variables
(let ((iterator (make-symbol "i"))
(end (make-symbol "end"))
(res (make-symbol "res")))
;; implementation
`(if (not (listp ,listvar))
(error (format "Wrong type of argument for LISTVAR: %s" ,listvar))
(let ((items ,listvar)
(,iterator 0)
(,end (length ,listvar))
(,res))
(while (< ,iterator ,end)
(setq ,loopvar (nth ,iterator items))
(setq ,res ,@body)
(setq ,iterator (+ 1 ,iterator))
)
,res))))
(defun push-append (newelt place)
(setcdr (last place) (cons newelt nil))
place)
(defun range (end &optional start step reverse)
;; defaults
(or start (setq start 0))
(or step (setq step 1))
(let ((i start) (res (list start)))
(while (< i end)
(setq i (+ i step))
(if reverse
(push i res)
(push-append i res)))
res))
(defun sum (&rest items)
(let ((res 0))
(for x in items
(setq res (+ res x)))))
(defun ! (n)
"Factorial calculation for N"
(if (and (numberp n) (>= n 0))
(if (eq n 0) (setq n 1))
(error "N has to be a non-negative integer"))
(apply '* (range n 1)))
;; examples
(range 5 1 2 t) ; => (5 3 1)
(apply 'sum (range 10)) ; => 55
(! 4) ; => 24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment