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