From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7777 invoked from network); 24 Oct 1999 05:56:43 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 24 Oct 1999 05:56:43 -0000 Received: (qmail 24484 invoked by alias); 24 Oct 1999 05:56:37 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 8387 Received: (qmail 24477 invoked from network); 24 Oct 1999 05:56:35 -0000 From: "Bart Schaefer" Message-Id: <991024055629.ZM1635@candle.brasslantern.com> Date: Sun, 24 Oct 1999 05:56:28 +0000 X-Mailer: Z-Mail (5.0.0 30July97) To: zsh-workers@sunsite.auc.dk Subject: Parameter module, $functions, and autoloading MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii A while back somebody asked about having local functions, i.e. functions that become unset when the function that defined them finishes. It struck me that this ought to be possible with the $functions parameter: zmodload parameter function bar() { echo bar at top level } function foo() { typeset +h functions function bar() { echo bar inside foo } bar } zagzig% foo bar inside foo zagzig% bar bar at top level zagzig% Unfortunately, this has an unwanted side-effect: All autoloaded functions that are still undefined, become defined to run the command "undefined". A workaround occurred to me: function foo() { alias undefined='unfunction $0 ; autoload -U $0 ; $0 "$@"' typeset +h functions function bar() { echo bar inside foo } bar } This works just fine provided that (a) FUNCTION_ARGZERO is set and (b) you were expecting "autoload -U" behavior on the function in question. There is currently no way to determine whether an autoload had -U or not. Combined with previous observations about vared (see zsh-users/2687), a fix for the `functions' parameter seems to be in order ... or does it? There's another long-standing "bug" that is related: eval "$(functions)" With autoloaded functions present, this produces a bodiless function named "undefined", along with empty functions replacing all autoloaded functions. This is even more insidious,as you don't even get an error when attempting to run one of the no-longer-autoloaded functions. An interesting solution to both problems occurred to me today: Create a builtin "undefined" that works like the alias above. That builtin could have access to the function name and argv independent of FUNCTION_ARGZERO, and would simply perform the autoload and execute. It could even take an option -U having the same meaning as "autoload -U". Then we change "functions" to output "foo() { undefined }" instead of the present format, et voila. One could then create an autoloaded function by assigning functions[foo]=undefined which is exactly what happens when the $functions AA is restored on exit from a local context. It's a shortcut for "unfunction foo; autoload foo". And the output for a function that was declared with "autoload -U" is "foo() { undefined -U }". A more complicated solution involves a minor parsing rewrite: Create a new reserved word "undefined". Parse it in a manner almost identical to the parsing for "function", except that an empty function body is required. That function is marked autoloaded. Then, one last bit of magic: If the function does not have a name -- which is already possible, e.g. look at the parse of "function foo() { function }" -- then the function containing the nameless function is marked autoloaded instead. With that in place, both undefined foo() { } and foo() { undefined } mean that foo is autoloaded, and then we don't have to change the output of the "functions" builtin. But that leaves unanswered the question of how to represent "autoload -U", because a reserved word can't "take options". I like the builtin-command idea better. Any comments? One final thought: It was also previously asked (by Adam?) whether there is some way to cause an autoloaded function to become defined without actually executing it. That could become an operation of the "undefined" command: Called with no arguments, it behaves as above, and gives an error if not in a function context; called with arguments, it resolves them as autoloads (or gives an error if it can't) but doesn't exectute. (We could of course choose another name than "undefined" for any of this.) -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.brasslantern.com