map and filter can run fast, but not always. If you are using a map, you can do some optimizations.
Let's use a timing function:
Code: Select all
;;
;; Time expressions for N times
;;
(define (time-expr _expressions _N)
  (if (not (apply = (map eval _expressions)))
    (begin
      (map (lambda (_e) (println _e " => " (eval _e))) _expressions)
      (throw-error "Return values of timed expressions do not match!")))
  (println)
  (letn (times (map (lambda (_e) (time (eval _e) _N)) _expressions)
         lentimes (apply max (map (lambda (x) (length (string x))) times))
         maxtime (apply max times))
    (if (= maxtime 0)
      (println "All times are 0!")
      (map (lambda (t _e) (println (format (append "%" (string lentimes) "d") t) " ms : " (format "%5.1f" (mul (div t maxtime) 100.0)) "% | " _e )) times _expressions))))
If you need to get the first value in the nested list 'lst', you can do:
This is quite fast. The rule is - try to stay away from mapping a lambda function. Doing that means that you are calling a function, passing an argument(s) and returning back from it. All that takes some time. Let's see timings for different cases:
Code: Select all
(setq lst (dup '(1 2 3) 1000))
(time-expr '((map first lst)
             (map (lambda (x) (first x)) lst)
             (begin (setq r '()) (dolist (x lst) (push (first x) r -1)) r)) 500)
----------------
266 ms :  60.7% | (map first lst)
438 ms : 100.0% | (map (lambda (x) (first x)) lst)
406 ms :  92.7% | (begin 
 (setq r '()) 
 (dolist (x lst) 
  (push (first x) r -1)) r)
Another example - add 2 to every element of a list:
Code: Select all
(setq lst (sequence 1 1000))
(time-expr '((map (lambda (x) (+ 2 x)) lst)
             (map + (dup 2 (length lst)) lst)
             (begin (setq r '()) (dolist (x lst) (push (+ 2 x) r -1)) r)) 800)
----------------
500 ms : 100.0% | (map (lambda (x) (+ 2 x)) lst)
328 ms :  65.6% | (map + (dup 2 (length lst)) lst)
328 ms :  65.6% | (begin 
 (setq r '()) 
 (dolist (x lst) 
  (push (+ 2 x) r -1)) r)
The trick is: Instead of using a lambda function, make additional list filled with constants:
And another example - multiply list elements by 2:
Code: Select all
(setq lst (sequence 1 1000))
(time-expr '((map (lambda (x) (* 2 x)) lst)
             (map * (dup 2 (length lst)) lst)
             (map + lst lst)
             (begin (setq r '()) (dolist (x lst) (push (+ x x) r -1)) r)) 800)
----------------
484 ms : 100.0% | (map (lambda (x) (* 2 x)) lst)
328 ms :  67.8% | (map * (dup 2 (length lst)) lst)
328 ms :  67.8% | (map + lst lst)
375 ms :  77.5% | (begin 
 (setq r '()) 
 (dolist (x lst) 
  (push (+ x x) r -1)) r)
Timings vary if run several times, but still show a general picture faster > slower.
Fanda