From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15047 invoked by alias); 30 Dec 2012 22:12:26 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 17513 Received: (qmail 13454 invoked from network); 30 Dec 2012 22:12:23 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <121230141200.ZM1230@torch.brasslantern.com> Date: Sun, 30 Dec 2012 14:12:00 -0800 In-reply-to: Comments: In reply to Russell Harmon "Re: Creating A Clean Environment For Autoloaded Functions" (Dec 30, 4:02pm) References: <121230112044.ZM879@torch.brasslantern.com> X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-users@zsh.org Subject: Re: Creating A Clean Environment For Autoloaded Functions MIME-version: 1.0 Content-type: text/plain; charset=us-ascii On Dec 30, 4:02pm, Russell Harmon wrote: } } On Sun, Dec 30, 2012 at 2:20 PM, Bart Schaefer } wrote: } > This amounts to asking how to violate a basic tenet of shell function } > behavior. They're supposed to act like commands that are always at the } > front of the search path, and the search path doesn't change based on } > the order in which every other command was added to it. } } I guess that breaking with this particular shell idiom is what I want } to do. Otherwise, how is one supposed to be able to create } autoloadable functions with reliable and reproducible behavior? As I said, you do it like this: } > The way you avoid this is to write every function that explicitly does } > not want this behavior so as to explicitly override it; for examply by } > using "command ls" instead of "ls". To be completely "reliable and reproducible" you also have to set up the emulation mode very carefully, force a fixed value of $path, etc. In practice is this is often more than either you or the caller of your function actually want. The alternative is to write scripts rather than autoloaded functions, which run in their own process and have more complete control of their context. Part of the reason for using functions rather than scripts is so that they operate in the context of the running shell, which implies that the caller is permitted to screw around with that context. } I'm thinking to add an option to autoload to undefine all functions } much like how -U works with aliases. The problem with that is that -U doesn't actually undefine the aliases, it just prevents them from being expanded at parse time. There is no equivalent parse-time mechanism for distinguishing an external command from a function. In zsh (and probably only in zsh of all shells) there actually is a way to remove all functions if you really want to. the_lonely_function() { builtin zmodload zsh/parameter builtin typeset +h functions builtin unfunction -m \* # # There are now no functions but this function, # and even this function cannot call itself. # On return, the local parameter scope will end # and other function definitions will reappear. # } There are a few obscure gotchas with this; for example, functions that were previously autoload-able will instead become real functions that use the "autoload -X" command to bootstrap. That may not always have the equivalent effect to the original autoload. } Basically, I'm trying to follow what the best practices are when } writing autoloadable functions so that they will be able to run } reliably in the largest number of different environments possible. I'd have to say that the *usual* practices are to worry about the emulation mode and setopts, use globbing and parameter expansion tricks to avoid reliance on external commands as much as possible, and to presume "autoload -U" has eliminated parse-time surprises. Beyond that and the judicious application of "builtin" or "command" prefixes where necessary, you're putting in too much effort for the incremental value.