ZSH Gem #12: Autoloading functions

Posted by | Comments (4) | Trackbacks (0)

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:

Trackbacks

No Trackbacks for this entry.

Comments

There have been 4 comments submitted yet. Add one as well!
Brandon Zylstra
Brandon Zylstra wrote on : (permalink)

$fpath is an array, just like $path, and $FPATH is colon-delimited, just like $PATH. What you said is true, but seems to imply inconsistency in Zsh when it is actually perfectly consistent (at least here: there may be inconsistencies elsewhere, of course).

Janek Bevendorff
Janek Bevendorff wrote on : (permalink)

Hi Brandon,

Thank you for your comment.
Actually, I didn’t want to imply an inconsistency, but rather wanted to give a little warning to people being used to $PATH.
But thanks for your addition. smile

Brandon Zylstra
Brandon Zylstra wrote on : (permalink)

Please remove the spam (And then this comment. Thanks.)

Janek Bevendorff
Janek Bevendorff wrote on : (permalink)

Thanks for the info. This was all trackback spam that came in just tonight and passed the filter because the trackbacks only had a spam score of 58%. There were also about 25 more trackbacks from the same bot which were caught.
Maybe I should disable trackbacks altogether. In about 90% of all cases they are simply used for spam and other than for normal comments there is no extra protection by hidden honeypots etc. Only the Bayes filter.

Write a comment:

HTML-Tags will be converted to Entities.
Textile-formatting allowed
Standard emoticons like :-) and ;-) are converted to images.
Design and Code Copyright © 2010-2017 Janek Bevendorff Content on this site is published under the terms of the GNU Free Documentation License (GFDL). You may redistribute content only in compliance with these terms. tweetbackcheck