elmacro was already mentioned by @lunaryorn, but as the author of this package I thought it'd be nice to seeprovide an example.
If you record a macro like this:
F3 C-e M-b M-u C-a C-n F4
Then doing M-x elmacro-show-last-macro upcase-last-word produces a buffer with:
(defun upcase-last-word ()
"Change me!"
(interactive)
(move-end-of-line 1)
(backward-word 1)
(upcase-word 1)
(move-beginning-of-line 1)
(next-line 1 1))