- dolist, dotimes.
- loop (which is pretty bad..)
- do (ok, but not too readable.)
- If i need a stack, recursively. (Unless a stack happens to fall in my lap, like the code in OP)
If you use callbacks to gather, you only need to have different functions for different ways of iterating. This is btw another advantage of this way over loop and iter, you can do: (Should've called :single-round \:once..) (all untested)
Code: Select all
(defun add-1 (list)
(umac ((:list) (:single-round)) (map nil (lambda (x) (collecting (+ x 1))))))
Code: Select all
(defun consa (list add) '(,@list ,add))
(defun add-1 (list)
(reduce (lambda (out el) (consa out (+ el 1)) list))
I have thought about higher functions, like when i thought about having (not function) be equivalent to (lambda (&rest rest) (not (function @rest))), or if there is spillover: (f-a f-b) eqv to (lambda ([stuff of f-b] [stuff of f-a]) (f-a (f-b [stuff of f-b]) [stuff-of-f-a])). Maybe i should make a little macro, maybe instead (ho () f-a f-b) can do that, or even (ho (f-d) f-a f-b f-c), that would make reduce look a lot more attractive.(f-d being arguments before f-a f-b f-c, etc. Ah shit i don't really see how to do the lambda in the defun right now. I need to think about this more.
With this stuff using functions taking functions as arguments would be much more attractive, not having to have (lambda (arguments) ..) floating around everywhere.
The umac macro i made here makes me doubt. Lets ask the question how we would make a lisp that does this with regular macros. I'd do it with scope; defvars, defun, defmacro, defsymbol-macro limited to the bodies of progn, lambda, etc. You could do pretty the thing i did with umac by having a scope-transparent-progn, and making the macro output a scope-transparent-progn have the defvars etc. in it. But then i ask of myself why still have a let, flet, macrolet?
Somewhat relatedly, i am also doubting whether s-expressions are really the way we should write everything. Sure, what we write should trivially be converted to s-expressions, but there is a lot that does that. not~expr -> (not expr) for single-argumented functions and numerically, a + b -> (+ a b), same for *, etc. would need to work out precidence.
The thing here that is related that we could write (def symbol expr) for a variable and (def (fun-name arguments) (progn body)) for functions, now we can think about scoping and call {...} (progn ...) and a := b (def a b), and we would get functions written more like ocaml or something.
Code: Select all
(defmacro for-list (el list &optional (iter (gensym))
(post-body `(progn ,iter = (cdr ,iter) /*Add to post-body*/
(when (null iter) (finish)))) /*Stop at end of list.*/
`(transparent-progn
,iter := ,list
(def-symbol-macro ,el (car ,iter))))
(defmacro equip-listing (&optional (out-var 'ret)) /*Ret being default return.*/
`(transparent-progn
(collecting &rest args) := { (append ,out-var (list args)) }
(appending &rest args) := { (append ,out-var args) }))
(add-list list &optional (add 1)) :=
{ (for-list el list) (equip-listing) /*Make this scope one that iterates a list, and get stuff to collect with.*/
(collecting (+ el add))
}