Not a Recursive Macro

When I first started my plan to concoct a classically recursive macro, I got as far as writing a complete, functioning implementation before I stopped to think and realised that what I’d been working on wasn’t actually a recursive algorithm at all but was in fact iterative. 🤦

But even though the macro below doesn’t actually fulfil the brief, I’m still kind of proud of the method I came up with for incrementing and testing the loop index, so I thought I’d post it here for posterity.

As with my other macros I’d recommend downloading the file and opening it in Vim so you can try it out1, but I’m also including the code below. If downloading isn’t CONVENIENT for you right now, you can just copy and paste it into a :new buffer to try the macro out.

"      ___   ____  __    _     ___   __   _   _      ____
" Not | |_) | |_  / /`  | | | | |_) ( (` | | \ \  / | |_
"     |_| \ |_|__ \_\_, \_\_/ |_| \ _)_) |_|  \_\/  |_|__
"      _       __    __    ___   ___
"     | |\/|  / /\  / /`  | |_) / / \
"     |_|  | /_/--\ \_\_, |_| \ \_\_/
"      ____  _   ___   ___   _       __    __    __    _
"     | |_  | | | |_) / / \ | |\ |  / /\  / /`  / /`  | |
"     |_|   |_| |_|_) \_\_/ |_| \| /_/--\ \_\_, \_\_, |_|

" Preamble: Write out a comment and the first two numbers of the sequence plus
" two trailing spaces. In order to keep track of how many members of the
" sequence we've generated, each time we calculate a number, we'll add another
" space.
let @p = "yiwo\<C-R>0 numbers of the Fibonacci sequence:\<CR>1 1  \<Esc>"

" Build the "recursive" algorithm
"
" Yank last number on line and paste at end
let @b = "g_yiwg_a \<Esc>p"

" Yank previous number
let @c = "2geyiw"

" Build macro in "e to increment by value in yank register
let @d = "O\<C-R>0\<C-V>\<C-A>\<Esc>0\"ey$dd"

" Add by playing back macro "e
let @a = "g_@e"

" Calculate next number in sequence
let @n = "@b@c@d@a"

" Increment counter by adding another space
let @i = "A \<Esc>"

" Test for end
"   1. Make a copy of the line and remove the spaces at end of line
"   2. Reyank target N
"   3. Build a macro to write a sequence of N 'N' characters
"   4. Yank and run it. Now the copied line contains the Fibonacci sequence
"      calculated so far, followed by a series of N Ns.
"   5. Replace entire line with blank characters (this is because when the
"      recursive macro ends, we won't get to remove this line. One alternative
"      I considered was setting 'nostartofline' and deleting the line with
"      `dd` instead of moving up)
"   6. Jump to end of line. Move up onto copied line. Attempt to move right.
"      if there are more Ns on the copied line than spaces at the end of the
"      real line, then this move will be successful, but if we've calculated N
"      numbers, there will be an "error", and the macro will stop running.
"   7. If we get to here, we haven't finished yet. Delete the copied line
"      ready for the next iteration..
let @t = "yyPg_lD-yiw+O\<C-R>0AN\<C-V>\<Esc>\<Esc>0y$dd@0Vr +$hlkldd"

" Recursive macro to calculate the requested digits of the sequence
let @f = "@n@i@t@f"

" Set up the final macro
let @q = "@p@f"

" So. To try this out, type the following, now:
"
"    :so %
"


" Set all options to default values
set all&


" vim:tw=78:ts=8:norl:nospell:
1,/DELETE_TO_HERE/d
" Place the cursor on any number, and then press    @q    to run the macro!
" Here's one for you to try: 12

The good news is, after I was done FACEPALMING, I wrote a version that is recursive, and then spent several years very slowly documenting it. For you! So if you haven’t already seen it, you should absolutely go check it out!


  1. Type :so % to load your registers with the macro, and then place your cursor on a number and enter @q to play it back. ↩︎