diff --git a/lispBM/README.md b/lispBM/README.md index f21444f1..0c726af7 100644 --- a/lispBM/README.md +++ b/lispBM/README.md @@ -1008,7 +1008,7 @@ Another example that prints "Hello World" every two seconds: (looprange it start end body) ``` -Range-loop. Iterate it from start to end and evaluate body for each iteration. The iterator can be accessed from within body. Example: +Range-loop. Iterate it from start to end and evaluate body for each iteration. The iterator it can be accessed from within body. Example: ```clj (looprange i 0 5 @@ -1030,6 +1030,34 @@ Output: )) ``` +#### loopforeach + +```clj +(loopforeach it lst body) +``` + +ForEach-loop. Iterate over every element in the list lst and evaluate body for each iteration. The iterator it can be accessed from within body. Example: + +```clj +(loopforeach i '("AB" "C" "dE" "f") + (print i) +) + +Output: +AB +C +dE +f + +; As with the other loops, multiple statements require a progn +(loopforeach i '("AB" "C" "dE" "f") + (progn + (print i) + (sleep 0.5) +)) + +``` + ### Useful Lisp Functions There are a number of lisp functions that can be used from lispBM in the VESC firmware. They will be loaded to the environment the first time they are used, so they do not use up memory before the first use. diff --git a/lispBM/lispif_vesc_dynamic_loader.c b/lispBM/lispif_vesc_dynamic_loader.c index e5f3592a..758140d8 100644 --- a/lispBM/lispif_vesc_dynamic_loader.c +++ b/lispBM/lispif_vesc_dynamic_loader.c @@ -111,6 +111,11 @@ static const char* macros[] = { "(define looprange (macro (it start end body)" "`(let ((loop (lambda (,it res)(if (< ,it ,end)(loop (+ ,it 1),body)res" "))))(loop ,start nil))))", + +"(define loopforeach (macro (it lst body)" +"`(let ((loop (lambda (,it rest res)" +"(if (eq ,it nil) res (loop (car rest) (cdr rest) ,body)" +")))) (loop (car ,lst) (cdr ,lst) nil))))", }; static bool strmatch(const char *str1, const char *str2) {