[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Lisp refactoring puzzle
From: |
PJ Weisberg |
Subject: |
Re: Lisp refactoring puzzle |
Date: |
Thu, 29 Mar 2012 18:51:14 -0700 |
On Tue, Jul 5, 2011 at 11:54 AM, Sean McAfee <eefacm@gmail.com> wrote:
> I use EMMS (Emacs Multi Media System) a lot, and I have the following
> key mappings set up to easily skip around inside large MP3s:
>
> (global-set-key [(super left)]
> (lambda () (interactive) (emms-seek -7)))
> (global-set-key [(super meta left)]
> (lambda () (interactive) (emms-seek -60)))
> (global-set-key [(super meta control left)]
> (lambda () (interactive) (emms-seek -360)))
>
> ...and likewise for the right arrow key, with positive arguments to
> emms-seek.
>
> These mappings are of course repetitive, and so a while back I wrote
> some code to set them up. As I became more familiar with the loop
> macro, I refined the code several times, until I got what I have today:
>
> (defconst skip-intervals '((7 . super) (60 . meta) (360 . control)))
>
> (loop for (magnitude . modifier) in skip-intervals
> collecting modifier into modifiers
> do (loop for key in '(right left)
> and delta = magnitude then (- magnitude)
> do (global-set-key
> (vector (append modifiers (list key)))
> `(lambda () (interactive) (emms-seek ,delta)))))
>
> This is fairly elegant, but I'm disappointed that it doesn't really save
> me any lines of code over just writing out the mappings by hand.
>
> Can anyone suggest a more compact/elegant way to establish these
> mappings?
You're trying to outsmart yourself. Refactoring isn't about trying to
fit all your logic into as few bytes of code as possible. Your first
set of three calls to `global-set-key' make it obvious exactly what
the code is doing. I had to stare at that loop for a minute before I
realized what the "collecting" part was trying to accomplish.
On the other hand, my brain won't ever let me leave a "how do you do
X?" question alone, so I went ahead anyway and wrote what I think is a
clearer way of doing what you're doing above.
(let ((skip-intervals '((7 . "s") (60 . "s-M") (360 . "s-M-C")))
(directions '(("left" . -1) ("right" . 1))))
(loop for (magnitude . modifier) in skip-intervals do
(loop for (direction . sign) in directions do
(global-set-key (read-kbd-macro (format "%s-<%s>"
modifier direction))
(lambda () (interactive) (emms-seek (*
sign magnitude)))))))
-PJ
Gehm's Corollary to Clark's Law: Any technology distinguishable from
magic is insufficiently advanced.