zsh-workers
 help / color / mirror / code / Atom feed
* Parameter module, $functions, and autoloading
@ 1999-10-24  5:56 Bart Schaefer
  1999-10-24 21:13 ` Zefram
  0 siblings, 1 reply; 3+ messages in thread
From: Bart Schaefer @ 1999-10-24  5:56 UTC (permalink / raw)
  To: zsh-workers

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


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Parameter module, $functions, and autoloading
  1999-10-24  5:56 Parameter module, $functions, and autoloading Bart Schaefer
@ 1999-10-24 21:13 ` Zefram
  1999-10-24 22:51   ` Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: Zefram @ 1999-10-24 21:13 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers

Bart Schaefer wrote:
>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".

Would be nice.  Autoloaded functions are already internally executed in
a manner pretty close to this; it's tempting to change autoload to just
define the function with a body consisting of a call to this builtin.

The only issue I see is, unfortunately, a biggie.  What happens if you
have a function defined like this, then the user defines "undefined"
as a shell function (taking precedence over the builtin) and then tries
to execute the supposedly-autoloaded function?  Also consider disabling
the builtin.  You'd need some special syntax, rather than just a command
name, to avoid this potential clash.

If you do go with a special syntax, I suggest that the syntax allow
an arbitrary command name, rather than just handling this one case of
autoloaded functions.  There may be other things in the future for which
we want non-overridable builtin command syntax.

>A more complicated solution involves a minor parsing rewrite:  Create a
>new reserved word "undefined".

We can't define any new reserved words and retain sh/ksh compatibility.
That's even worse than a builtin.

Oh, I suggest that the name "autoloaded" is clearer than "undefined",
if we do do any of this.  I never liked that bit of the `functions`
format: if a function is undefined, surely it doesn't exist at all,
and shouldn't be output.

-zefram


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Parameter module, $functions, and autoloading
  1999-10-24 21:13 ` Zefram
@ 1999-10-24 22:51   ` Bart Schaefer
  0 siblings, 0 replies; 3+ messages in thread
From: Bart Schaefer @ 1999-10-24 22:51 UTC (permalink / raw)
  To: Zefram; +Cc: zsh-workers

On Oct 24, 10:13pm, Zefram wrote:
} Subject: Re: Parameter module, $functions, and autoloading
}
} Bart Schaefer wrote:
} >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".
} 
} Would be nice.  Autoloaded functions are already internally executed in
} a manner pretty close to this; it's tempting to change autoload to just
} define the function with a body consisting of a call to this builtin.

Yes.

} The only issue I see is, unfortunately, a biggie.  What happens if you
} have a function defined like this, then the user defines "undefined"
} as a shell function (taking precedence over the builtin) and then tries
} to execute the supposedly-autoloaded function?  Also consider disabling
} the builtin.  You'd need some special syntax, rather than just a command
} name, to avoid this potential clash.

Ah, yes; but we already have just such a syntax ...
 
} Oh, I suggest that the name "autoloaded" is clearer than "undefined",
} if we do do any of this.

How about this:  Rather than "autoloaded" or "undefined" we just make it
an option to "autoload" itself.  -X, perhaps, for "eXecute"?  And another
one, perhaps -I for "Immediate" or -e for "evaluate", that loads in the
definition without calling it?

And then "autoload -U foo" defines foo as

	foo() { builtin autoload -UX }

(Or even

	foo() { builtin autoload -UX foo "$@" }

if that seems more appropriate than having "autoload -X" with no args get
the surrounding context magically; but I lean to the former, to avoid any
ambguity about what is done with "$@" in that latter example.)

If someone does "disable builtin" they're going to be in deep doodoo in
any event.  And it seems reasonable to expect that if they're creating
functions with "autoload" in the first place, then it won't be disabled
when the functions are called.

} I never liked that bit of the `functions` format: if a function is
} undefined, surely it doesn't exist at all, and shouldn't be output.

I was afraid it was that way to dupicate ksh's output, or something.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1999-10-24 22:52 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-10-24  5:56 Parameter module, $functions, and autoloading Bart Schaefer
1999-10-24 21:13 ` Zefram
1999-10-24 22:51   ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).