Is there something like closures for zsh?

Zsh doesn't have anything like closures or packages or namespaces. Zsh lacks a bunch of things required to have true closures:

  • Functions aren't first class. You can't pass functions around as arguments to other functions, and functions can't return other functions. (You can pass the name of a function to call, but that's not the same as passing the function itself).

  • You can't have nested functions. All functions in zsh are global. You must prefix your function names to avoid conflicts. Note especially that functions will shadow external programs with the same name. If you have a function called ls, it will be called instead of the program ls. This can be useful, except if you do it by accident.

  • Variables are dynamically scoped, not statically scoped like in most modern languages. Even if you could have nested functions, inner functions wouldn't close over the local variables of outer functions in the way you would normally expect. You couldn't use them to make modules the way people do in, say, Javascript.

  • Zsh does have anonymous functions, but without any of these other things they're not useful for much.

So basically, the best you can do is to prefix all your functions and global variables.

I'll also point out that you should do define your precmd like this:

% autoload -Uz add-zsh-hook
% add-zsh-hook precmd my_precmd_function

add-zsh-hook lets you hook your function into precmd without it overwriting any other functions that might also want to hook precmd.

What it means to have a function loaded is a separate question. Zsh has an autoloading feature that only loads functions from disk when they're actually called. When you do autoload -Uz foobar, that makes the function named foobar available to call. When you actually call foobar, that loads the definition from disk.


No, closures are too sophisticated for zsh. Zsh is designed to interpret small scripts that are not far removed from direct interaction. It doesn't have fancy language features that are very useful for programming in the large but less so for the kind of small tasks that shells are typically used for.

Note that if there was some form of closure that allowed the value of the variables to be pre-computed once and for all and then stored, the values would not be updated when something changes that causes the information to become invalid.

$git_info and the derived variables can change at any time due to a modification to a file checked into git or to the git repository. So they need to be recomputed each time anyway.

You could cache the values of cwd and who_where in a global variable, since they don't change under normal operation. cwd changes when the currrent directory changes so it would need to be updated from chpwd. However, these variables are extremely quick to compute, so there is no point in bothering. The expensive computation here is running git_prompt_info, and that can change at any time.

When you're displaying information between each command, it may be a better idea to put it as part of the prompt (PS1 or the psvar array). Zsh knows that it must redisplay the prompt in a variety of circumstances, whereas it knows nothing about what you print from precmd.