ZSH Gem #12: Autoloading functions
Have you ever wondered why ZSH provides so many features but is still so fast? That's because of its autoloading mechanism. Functions can be marked as empty so they aren't loaded before they are executed the first time. This saves a lot of memory and much processing power.
The base of this autoloading mechanism is the shell parameter $fpath
. This variable contains all the paths where function definition files are located. You can view them with:
echo $fpath
In current versions of ZSH this should give you a long list of directories all containing files with function definitions. We can also add our own directory to it:
mkdir myfndir
fpath=($fpath myfndir)
Note: Unlike $PATH
, $fpath
is not a delimiter separated string. It is an array. So just adding mydir
using string concatenation would break your shell!
Now that we have added our own directory we can create our first function. Normally functions always have a function definition and body. However, the files for autoload functions only contain the body. So to create an autoload function foobar
we need to create a file called foobar
inside our autoload directory with the body of our function (without any surrounding braces):
# Some autoload function
echo "Hello World"
Until now nothing happens when we call foobar
on the command line. That's because we haven't marked it for autoloading yet. To do that run:
autoload foobar
This will mark the function for autoloading. It is important to know that the function has not yet been executed in any way. autoload
just creates an empty function definition. The function body will be loaded from the file the first time the function is called. You can prove that by renaming our file and calling the function:
mv myfndir/foobar myfndir/foobarbaz
foobar
You'll get the error message zsh: foobar: function definition file not found. If you rename the file back:
mv myfndir/foobarbaz myfndir/foobar
and call the function again, the file will be loaded into memory for execution without any problems. If you now rename the source file again, the function will still be able to run.
This autoloading mechanism ensures that the shell stays fast and snappy even though it provides a lot of features. Marking functions to be autoloaded with the autoload
command only has a very small memory footprint.
Now you should be able to write your own autoload functions, but before we call it quits for today let me show you one more very important thing. You might have noticed the -U
parameter I used in some of the previous articles when I invoked the autoload
command. This parameter prevents the expansion of aliases. Imagine what would happen if you had an autoload function called myfunction
with the following contents:
echo "This is some example file"
And you had the following alias definition in your .zshrc
:
alias echo="shutdown -h now"
If we'd load and execute our function as root
autoload myfunction
myfunction
it would be a big surprise what it actually does. Okay, I admit: you normally wouldn't alias echo
to shutdown
or something similar, but I think you know what I mean. Custom alias definitions could break some functions. In the best case the function would only be unable to run. In the worst case it might do some dangerous stuff. The -U
parameter prevents alias expansion inside autoload functions. Even though you had aliased echo
to rm -R /
the function would still work properly without any unintended side-effects. Therefore it is a good idea to autoload all functions with this parameter unless you know what you do.
Read more about autoloading functions: