Skip to content

Instantly share code, notes, and snippets.

@fukamachi
Created February 4, 2014 03:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fukamachi/8797790 to your computer and use it in GitHub Desktop.
Save fukamachi/8797790 to your computer and use it in GitHub Desktop.
(defmacro execution-time (&body body)
"Return the number of milliseconds it takes to execute `body`. Also
returns the result as the second value."
(let ((tm (gensym))
(res (gensym)))
`(let* ((,tm (get-internal-real-time))
(,res (progn ,@body))
(,tm (floor (* 1000 (- (get-internal-real-time) ,tm))
internal-time-units-per-second)))
(values (float ,tm) ,res))))
(defmacro aif (test then &optional else)
`(let ((it ,test))
(if it
,then
,else)))
(defun test-a ()
(aif (random 100)
'true
'false))
(defun test ()
(if (random 100)
'true
'false))
(let ((anaphoric (/ (loop repeat 5 sum (execution-time (loop repeat 10000000 do (test-a)))) 5))
(not-anaphoric (/ (loop repeat 5 sum (execution-time (loop repeat 10000000 do (test)))) 5)))
(format t "~&Anaphoric: ~A msec / Not-Anaphoric: ~A msec~%It's ~A % slower."
anaphoric
not-anaphoric
(* (/ (- anaphoric not-anaphoric) not-anaphoric) 100)))
@snmsts
Copy link

snmsts commented Feb 4, 2014

how about it?

(defvar *anaphoric-it* 'it)

(defmacro aif (test then &optional else)
  (assert (symbolp *anaphoric-it*))
  (labels ((find-it (e it)
             (cond ((eq e it) t)
                   ((listp e)
                    (loop for e in e
                       thereis (find-it e it))))))
    (if (or (find-it then *anaphoric-it*)
            (find-it else *anaphoric-it*))
        `(let ((,*anaphoric-it* ,test))
           (if ,*anaphoric-it*
               ,then
               ,else))
        `(if ,test ,then ,else))))

@fukamachi
Copy link
Author

I thought it at the beginning, but I threw the idea away because it doesn't work in these situations.

(aif (+ 1 1)
     (let ((it 10))
       (princ it))
     'false)

(flet ((it () (princ "Yeah!")))
  (aif (+ 1 1)
       (it)
       'false))

These are very trivial cases, though.

@al-skobelev
Copy link

I'm voting against modifying if. It is so basic construct, so I'd not expect it has any side effects. It is a good thing to have aif yet. Maybe it is worth to rename it to if-it to make the side-effect clearer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment