zsh-users
 help / color / mirror / code / Atom feed
* autoload
@ 2015-09-17 15:54 Ray Andrews
  2015-09-17 17:34 ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-17 15:54 UTC (permalink / raw)
  To: Zsh Users

Bart:

I did this, which should be verbatim as you posted:


     # Assume starting here with the default $fpath
     zsh_default_functions=~/.zsh-default-functions.zwc
     if ! zcompile -t $zsh_default_functions >&/dev/null
     then
       # File is missing or out of date.  Rebuild it.
       # Removes the file if any function cannot be compiled.
       zcompile $zsh_default_functions $^fpath/*(N.:A)
     fi
     if [[ -f $zsh_default_functions ]]
     then
       fpath=( $zsh_default_functions )
       autoload -w $zsh_default_functions
     fi

... and I get:

     /aWorking/Zsh/Boot/ztest:5: parse error near `)'
     /aWorking/Zsh/Boot/ztest:zcompile:10: can't read file: /usr/share 
                 /zsh/functions/Completion /Base.zwc

('ztest' being sourced by .zshrc and where I do experiments.)

'Base.zwc' exists:

     $ ls -l Base.zwc
     -rw-r--r-- 1 root root 269472 Aug 31 16:26 Base.zwc

... and  "zcompile -t Base.zwc" doesn't report anything amiss.

The  " parse error near `)' " msg. is puzzling since it always reports 
line 5 regardless of anything added above it ,eg: "echo "this echo is 
only here to add a line of code"".

For example if I modify your code like this:

     line5
         # Assume starting here with the default $fpath
zsh_default_functions=~/.zsh-default-functions.zwc
     line9

... I get this:

     /aWorking/Zsh/Boot/ztest:5: command not found: line5
     /aWorking/Zsh/Boot/ztest:9: command not found: line9
     /aWorking/Zsh/Boot/ztest:5: parse error near `)'
     /aWorking/Zsh/Boot/ztest:zcompile:14: can't read file: /usr/share 
/zsh/functions/Completion/Base.zwc

... so the deliberate errors are as expected, yet she insists on finding 
an `)' error on line 5 as well, and that after having reached line 9, so 
I have no idea how to understand that.




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

* Re: autoload
  2015-09-17 15:54 autoload Ray Andrews
@ 2015-09-17 17:34 ` Bart Schaefer
  2015-09-17 19:22   ` autoload Ray Andrews
  2015-09-19  0:14   ` autoload Bart Schaefer
  0 siblings, 2 replies; 45+ messages in thread
From: Bart Schaefer @ 2015-09-17 17:34 UTC (permalink / raw)
  To: Zsh Users

On Sep 17,  8:54am, Ray Andrews wrote:
} Subject: autoload
}
}      # Assume starting here with the default $fpath

I think the problem here is that you've put a .zwc file IN a directory
that is itself listed in $fpath.  This is typically a no-no.  You want
a .zwc file to be treated as if it WERE a directory, NOT as if it were
one of the function definition files IN the directory.

If you must have the .zwc where you've presently got it, then you need
to exclude it from the file pattern $^fpath/*(N.:A) -- which is easiest
if you have extendedglob set, so you can write $^fpath/*~*.zwc(N.:A)
instead.

}      /aWorking/Zsh/Boot/ztest:5: parse error near `)'
}      /aWorking/Zsh/Boot/ztest:zcompile:10: can't read file: /usr/share 
}                  /zsh/functions/Completion /Base.zwc

See, zcompile (without the -t) is attempting to parse Base.zwc as a
function definition, and getting what looks like garbage to the parser.
(I have no idea where those spaces in the path are coming from.)


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

* Re: autoload
  2015-09-17 17:34 ` autoload Bart Schaefer
@ 2015-09-17 19:22   ` Ray Andrews
  2015-09-17 20:40     ` autoload Bart Schaefer
  2015-09-19  0:14   ` autoload Bart Schaefer
  1 sibling, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-17 19:22 UTC (permalink / raw)
  To: zsh-users

On 09/17/2015 10:34 AM, Bart Schaefer wrote:
> On Sep 17,  8:54am, Ray Andrews wrote:
> } Subject: autoload
> }
> }      # Assume starting here with the default $fpath
>
> I think the problem here is that you've put a .zwc file IN a directory
> that is itself listed in $fpath.  This is typically a no-no.  You want
> a .zwc file to be treated as if it WERE a directory, NOT as if it were
> one of the function definition files IN the directory.

I'm close to certain I haven't, here's all .zwc on my system:


> /usr/share/zsh/functions/VCS_Info/Backends.zwc
> /usr/share/zsh/functions/Exceptions.zwc
> /usr/share/zsh/functions/VCS_Info.zwc
> /usr/share/zsh/functions/Prompts.zwc
> /usr/share/zsh/functions/MIME.zwc
> /usr/share/zsh/functions/Completion.zwc
> /usr/share/zsh/functions/TCP.zwc
> /usr/share/zsh/functions/Zle.zwc
> /usr/share/zsh/functions/Chpwd.zwc
> /usr/share/zsh/functions/Misc.zwc
> /usr/share/zsh/functions/Calendar.zwc
> /usr/share/zsh/functions/Completion/Debian.zwc
> /usr/share/zsh/functions/Completion/X.zwc
> /usr/share/zsh/functions/Completion/openSUSE.zwc
> /usr/share/zsh/functions/Completion/AIX.zwc
> /usr/share/zsh/functions/Completion/Mandriva.zwc
> /usr/share/zsh/functions/Completion/Base.zwc
> /usr/share/zsh/functions/Completion/Zsh.zwc
> /usr/share/zsh/functions/Completion/Linux.zwc
> /usr/share/zsh/functions/Completion/Cygwin.zwc
> /usr/share/zsh/functions/Completion/Solaris.zwc
> /usr/share/zsh/functions/Completion/Darwin.zwc
> /usr/share/zsh/functions/Completion/Redhat.zwc
> /usr/share/zsh/functions/Completion/BSD.zwc
> /usr/share/zsh/functions/Completion/Unix.zwc
> /usr/share/zsh/functions/Zftp.zwc
> /usr/share/zsh/functions/Newuser.zwc
>
>
> See, zcompile (without the -t) is attempting to parse Base.zwc as a
> function definition, and getting what looks like garbage to the parser.
> (I have no idea where those spaces in the path are coming from.)
>
It isn't possible I've somehow screwed up $fpath?  I understand it's 
hard coded at startup,
least it seems to always be restored. Anyhow I've not moved or played 
with Base.zwc.  I did try
creating a .zwc yesterday but it's long dead.

This seems to be the troublesome line:

      zcompile $zsh_default_functions $^fpath/*(N.:A)

... on a hunch:

      zcompile $zsh_default_functions $^fpath/*(N.:t)  << 't' being a 
new friend

... the previous error msgs are gone but:

     $ zsh
     /aWorking/Zsh/Boot/ztest:zcompile:13: can't open file: _bootctl



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

* Re: autoload
  2015-09-17 19:22   ` autoload Ray Andrews
@ 2015-09-17 20:40     ` Bart Schaefer
  2015-09-17 23:06       ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-17 20:40 UTC (permalink / raw)
  To: zsh-users

On Sep 17, 12:22pm, Ray Andrews wrote:
} Subject: Re: autoload
}
} On 09/17/2015 10:34 AM, Bart Schaefer wrote:
} >
} > I think the problem here is that you've put a .zwc file IN a directory
} > that is itself listed in $fpath.
} 
} I'm close to certain I haven't, here's all .zwc on my system:

The issue isn't (just) what your .zwc files are, it's also what you
$fpath contains at the time that your .zshrc or whatever is loaded.

E.g. $^fpath/*(.) appears to include
    /usr/share/zsh/functions/Completion/Base.zwc
as one of the matching files.

Therefore /usr/share/zsh/functions/Completion must be in the default
$fpath, and what I'm saying is that you should not normally put Base.zwc
in a directory that is in $fpath.

} It isn't possible I've somehow screwed up $fpath?  I understand it's 
} hard coded at startup,

Yes, and the problem is that you've put .zwc files into the directories
in that hardcoded list, but then tried to use the hardcoded list to
(re)build yet another .zwc file.

I'm not really sure how further to explain this.  The sample code that
I provided takes EVERY DIRECTORY that's in (the default) $fpath and
packs ALL the files under them into ONE .zwc.

You on the other hand seem to have already built a separate .zwc out of
EACH directory of the default $fpath.  If you're using my example, you
don't need to do that - you should throw all those .zwc away and use
the single one that my sample builds.

Or conversely you should not use that example.

}       zcompile $zsh_default_functions $^fpath/*(N.:t)  << 't' being a 
} new friend

A different enemy, more like.

} ... the previous error msgs are gone but:
} 
}      $ zsh
}      /aWorking/Zsh/Boot/ztest:zcompile:13: can't open file: _bootctl

The :t discards /usr/share/zsh/... and leaves just a base file name;
that might work for autoload but won't for zcompile.  You need the
full paths, just not the .zwc files.


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

* Re: autoload
  2015-09-17 20:40     ` autoload Bart Schaefer
@ 2015-09-17 23:06       ` Ray Andrews
  2015-09-17 23:20         ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-17 23:06 UTC (permalink / raw)
  To: zsh-users

On 09/17/2015 01:40 PM, Bart Schaefer wrote:
> Yes, and the problem is that you've put .zwc files into the directories
> in that hardcoded list, but then tried to use the hardcoded list to
> (re)build yet another .zwc file.
But I didn't create those files. They're dated August 31 which seems to 
be common to
most of the files in the distro as I downloaded it.  Is this something 
to do with Debian?

> I'm not really sure how further to explain this.  The sample code that
> I provided takes EVERY DIRECTORY that's in (the default) $fpath and
> packs ALL the files under them into ONE .zwc.
That's how I read it.

     You on the other hand seem to have already built a separate .zwc 
out of EACH
     directory of the default $fpath. If you're using my example, you 
don't need to
     do that - you should throw all those .zwc away and use the single 
one that my
     sample builds.


I tried deleting all of them which resulted in ~/.zsh-default-functions.zwc
being created, but zero length and of course nothing worked.  With 
original .zshrc code, things worked but a 'time' test was very slow, 
thus demonstrating the effectiveness of the .zwc
idea itself (by it's absence, in this case). I restored the .zwc files 
and I'm back to normal.
This seems to be a very tricky business.  Perhaps not worth wasting your 
time on.  It seems
a shame that zcompile doesn't know not to trip over itself, one might 
expect to find a .zwc
file in the same dir as the files from which it was built.  Or not.

> }       zcompile $zsh_default_functions $^fpath/*(N.:t)  << 't' being a
> } new friend
>
> } A different enemy, more like.
>

Sure, it was just experiment, I hardly expected it to be correct.


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

* Re: autoload
  2015-09-17 23:06       ` autoload Ray Andrews
@ 2015-09-17 23:20         ` Bart Schaefer
  2015-09-18  1:20           ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-17 23:20 UTC (permalink / raw)
  To: zsh-users

On Sep 17,  4:06pm, Ray Andrews wrote:
} Subject: Re: autoload
}
} But I didn't create those files. They're dated August 31 which seems
} to be common to most of the files in the distro as I downloaded it. Is
} this something to do with Debian?

Possibly.  I've never installed a pure Debian distro, only Ubuntu.

} I tried deleting all of them which resulted in ~/.zsh-default-functions.zwc
} being created, but zero length and of course nothing worked.

That's a little confusing since with :t in there you at least got an
attempt to read _bootctl so there must be some function files.

What does

() { emulate -L zsh -o extendedglob; print -lR $^fpath/*~*.zwc(N.:A) | head }

output, if placed early in your startup files (before you do any of your
own changes to $fpath)?


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

* Re: autoload
  2015-09-17 23:20         ` autoload Bart Schaefer
@ 2015-09-18  1:20           ` Ray Andrews
  2015-09-18  4:04             ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-18  1:20 UTC (permalink / raw)
  To: zsh-users

On 09/17/2015 04:20 PM, Bart Schaefer wrote:
> On Sep 17,  4:06pm, Ray Andrews wrote:
> } Subject: Re: autoload
> }
> } But I didn't create those files. They're dated August 31 which seems
> } to be common to most of the files in the distro as I downloaded it. Is
> } this something to do with Debian?
>
> Possibly.  I've never installed a pure Debian distro, only Ubuntu.
My first distro was Mint, and 'downgrading' to plain vanilla Debian was 
the smartest thing
I ever did--less baloney all 'round.   I don't even know what it is that 
I'm supposed to be
missing.  Anyway, those .zwc files are in the Debian package, I just 
checked.  Perhaps Axel
has a comment?
>
>
> That's a little confusing since with :t in there you at least got an
> attempt to read _bootctl so there must be some function files.
That's with 't' gone, and back to 'A'.
> What does
>
> () { emulate -L zsh -o extendedglob; print -lR $^fpath/*~*.zwc(N.:A) | head }
>
> output, if placed early in your startup files (before you do any of your
> own changes to $fpath)?
>
0 HP-w5--5-Debian1 /aWorking/Zsh 2$ zsh
/usr/local/share/zsh/site-functions/n-aliases
/usr/local/share/zsh/site-functions/n-cd
/usr/local/share/zsh/site-functions/n-env
/usr/local/share/zsh/site-functions/n-functions
/usr/local/share/zsh/site-functions/n-history
/usr/local/share/zsh/site-functions/n-kill
/usr/local/share/zsh/site-functions/n-list
/usr/local/share/zsh/site-functions/n-list-draw
/usr/local/share/zsh/site-functions/n-list-input
/usr/local/share/zsh/site-functions/n-options


... without 'head' it shows everything and it all looks fine.


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

* Re: autoload
  2015-09-18  1:20           ` autoload Ray Andrews
@ 2015-09-18  4:04             ` Bart Schaefer
  2015-09-18  5:00               ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-18  4:04 UTC (permalink / raw)
  To: zsh-users

On Sep 17,  6:20pm, Ray Andrews wrote:
} Subject: Re: autoload
}
} Anyway, those .zwc files are in the Debian package, I just checked.

In that case you should probably just do:

    autoload -w $^fpath/*.zwc(N)

and forget about rebuilding from the source functions.

-- 
Barton E. Schaefer


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

* Re: autoload
  2015-09-18  4:04             ` autoload Bart Schaefer
@ 2015-09-18  5:00               ` Ray Andrews
  2015-09-18  5:52                 ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-18  5:00 UTC (permalink / raw)
  To: zsh-users

On 09/17/2015 09:04 PM, Bart Schaefer wrote:
> On Sep 17,  6:20pm, Ray Andrews wrote:
> } Subject: Re: autoload
> }
> } Anyway, those .zwc files are in the Debian package, I just checked.
>
> In that case you should probably just do:
>
>      autoload -w $^fpath/*.zwc(N)
>
> and forget about rebuilding from the source functions.
Yes, that was quite the red herring there.  Interesting that Debian does 
things
differently like that.  I suppose they are free to, but it still seems 
strange that
there'd be no doc to the effect that their package is different from 
std. like that.
Maybe it's not to be expected.  I guess the 'line 5 `)' error mystery is 
best
forgotten.  Very strange tho.

I'm trying to get the autoload system working with my own functions and I'm
almost there.  " /aWorking/Zsh/Source"  is where they live, and I've 
called them
like this:

     for aa in /aWorking/Zsh/Source/*; do source $aa; done

... which was the first thing I learned about such things.  They are all 
'normal'
functions and most files contain more than one.

Now I'm trying this:

$ fpath=( /aWorking/Zsh/Source "${fpath[@]}" )
     $ source miscfunctions
$ autoload -w /aWorking/Zsh/Source/Source.zwc
$ l
     [ nothing ]
     $ l
     [ now I get listing ]

... in the docs there's talk of this--loading vs. loading and 
executing--but I can't
figger it.  I've tried 'zcompile -k/z ...' and 'autoload k/z ...' but no 
combination seems
to prevent the first call to any function from being inert. 'zcompile -t 
...' always
shows me a list of files, not functions.  Strangely there seems
to be no trouble with multiple functions in one file except in the case of
'miscfunctions' so I have to source it separately.  (The other multiple 
functions
are all help functions only called by the main function in each file. I 
don't know
why that makes a difference, but it does.)  Also, I wonder why $fpath 
needs to
be modified since 'autoload -w' is given an explicit path to the .zwc 
file, so should
hardly be concerned with looking for it via $fpath.  I'd expect it to be 
hashed
and that's that.



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

* Re: autoload
  2015-09-18  5:00               ` autoload Ray Andrews
@ 2015-09-18  5:52                 ` Bart Schaefer
  2015-09-18 15:49                   ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-18  5:52 UTC (permalink / raw)
  To: zsh-users

On Sep 17, 10:00pm, Ray Andrews wrote:
}
} I guess the 'line 5 `)' error mystery is best
} forgotten.  Very strange tho.

It's not a mystery.  Try this:

    zsh -nf /usr/share/zsh/functions/Completion/Base.zwc

} $ fpath=( /aWorking/Zsh/Source "${fpath[@]}" )
} $ source miscfunctions
} $ autoload -w /aWorking/Zsh/Source/Source.zwc
} $ l
} [ nothing ]
} $ l
} [ now I get listing ]

The way autoload works is, the name of the file has to be the same as
the name of the function.  If you "source" the file, you execute the
file contents immediately, which in your case defines the functions.
If you "autoload" the function names, you NEITHER define NOR execute
them; you just mark them to be processed later.

Then when you try to execute, zsh looks for a file with the same name
as the function, parses it, and executes the result of the parse.
Except for handling of the positional parameters, this is *almost* the
same as

   functions[$filename:t]=$(<filename)
   eval "$functions[$filename:t]"

With "autoload -z" (the default when no option), zsh assumes the file
*was* the entire function body and does nothing further.

*If* the function was marked "autoload -k", then zsh assumes that the
eval-like step defined THAT function, and calls it by name a second time,
similar to:

   functions[$filename:t]=$(<filename)
   eval "$functions[$filename:t]"
   $filename:t

If we now throw zcompile into the mix, the -z / -k options to autoload
are ignored in favor of the -z / -k options to zcompile.  However, the
rule about the file name having to be the same as the function name
doesn't change.  Further "autoload -w" still doesn't define anything;
it just uses the index table in the zcompiled file to grab the list
of names to mark for later processing.

} Strangely there seems to be no trouble with multiple functions in one
} file except in the case of 'miscfunctions' so I have to source it
} separately. (The other multiple functions are all help functions only
} called by the main function in each file. I don't know why that makes
} a difference, but it does.)

Does what I just wrote, above, help?  In the "miscfunctions" case, the
name of the file matches NONE of the names of the functions inside it;
they can't be autoloaded.  The name of the file has to match the name
of AT LEAST ONE function inside the file, *OR* the entire file has to
be that single function (as if it were a script).

} Also, I wonder why $fpath needs to be modified since 'autoload -w' is
} given an explicit path to the .zwc file

The internal implementation of autoloaded functions is unrelated to
hashing and does not retain any file paths.  It keeps only the base
names.  Where that set of names came from does not change that.

This is important to the consistent operation of fpath searching.  If
you have

    fpath=(/tmp/testfunctions ...)

and you create a new file /tmp/testfunctions/tryme, and the function
is marked for autoloading, then that new file has to be found ahead
of anything else, even if you previously used "autoload -w" on a .zwc
file that contains a "tryme" file.  The contents of fpath at the
instant of execution ALWAYS takes precedence; there is no "never get
this function from anywhere except [here]" in the autoload scheme.


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

* Re: autoload
  2015-09-18  5:52                 ` autoload Bart Schaefer
@ 2015-09-18 15:49                   ` Ray Andrews
  2015-09-18 16:52                     ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-18 15:49 UTC (permalink / raw)
  To: zsh-users

On 09/17/2015 10:52 PM, Bart Schaefer wrote:
> It's not a mystery.  Try this:
>
>      zsh -nf /usr/share/zsh/functions/Completion/Base.zwc
Ah, so the error is really from some other file.  I assumed it was some 
sort of
second parsing or something.  Nice if the called file was identified tho.
Anyway at least that's clear.

> If we now throw zcompile into the mix, the -z / -k options to autoload
> are ignored in favor of the -z / -k options to zcompile.  However, the
> rule about the file name having to be the same as the function name
> doesn't change.  Further "autoload -w" still doesn't define anything;
> it just uses the index table in the zcompiled file to grab the list
> of names to mark for later processing.
This could be made clearer in the docs.
> } Strangely there seems to be no trouble with multiple functions in one
> } file except in the case of 'miscfunctions' so I have to source it
> } separately. (The other multiple functions are all help functions only
> } called by the main function in each file. I don't know why that makes
> } a difference, but it does.)
>
> Does what I just wrote, above, help?  In the "miscfunctions" case, the
> name of the file matches NONE of the names of the functions inside it;
> they can't be autoloaded.  The name of the file has to match the name
> of AT LEAST ONE function inside the file, *OR* the entire file has to
> be that single function (as if it were a script).
I see.  Nuts, there's nothing about that in the docs is there?

> ...  The contents of fpath at the
> instant of execution ALWAYS takes precedence; there is no "never get
> this function from anywhere except [here]" in the autoload scheme.
>
As always Bart you make things as clear as they can be, but it sure is 
obtuse.  I long for:

     $ autoload --just_DO_IT  Source.zwc

... that is functionally identical to:

     $ for aa in /aWorking/Zsh/Source/*; do source $aa; done

( Of course that's after having done:)

      $ zcompile --just_DO_IT  Source.zwc  /aWorking/Zsh/Source/*


... but much faster--all functions are pre-digested to word code and 
ready for action, only not loaded into memory until/unless actually 
called.  'zcompile --just_DO_IT' is smart enough to create function 
names after filenames in the case of scripts, and of course named 
functions are named functions.  No need for wandering around in $fpath, 
the names of all the functions found in '.../Source' (regardless of the 
name of any file except in the case of scripts) and their definition 
.zwc are tabled for instant access so the user can consider them as 
having been sourced already, it's just much faster and trimmer.  (Speed 
is the point of all this, right?) "zcompile -t --just_DO_IT Source.zwc" 
returns the list of all *functions* found or created (from scripts) in 
'Source.zwc'.

Never mind, like completion, this is not for mortals to dabble in. My 
'for' loop does it all in one line and there's no gotchas. Transparency 
is not a zsh virtue.




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

* Re: autoload
  2015-09-18 15:49                   ` autoload Ray Andrews
@ 2015-09-18 16:52                     ` Bart Schaefer
  2015-09-18 18:29                       ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-18 16:52 UTC (permalink / raw)
  To: zsh-users

On Sep 18,  8:49am, Ray Andrews wrote:
}
} > If we now throw zcompile into the mix, the -z / -k options to autoload
} > are ignored in favor of the -z / -k options to zcompile.  However, the
} > rule about the file name having to be the same as the function name
} > doesn't change.  Further "autoload -w" still doesn't define anything;
} > it just uses the index table in the zcompiled file to grab the list
} > of names to mark for later processing.
} 
} This could be made clearer in the docs.
[...]
} I see.  Nuts, there's nothing about that in the docs is there?

There's an entire section for "Autoloading Functions" but it has no
cross-reference from the "autoload" builtin (autoload points to
functions points to typeset which finally does have the section
reference).  I'll rearrange this a bit.

There IS a cross-reference to that section from the zcompile builtin.

}      $ autoload --just_DO_IT  Source.zwc
} 
} ... that is functionally identical to:
} 
}      $ for aa in /aWorking/Zsh/Source/*; do source $aa; done

You can do that:

FPATH=/aWorking/Zsh/Source autoload +X -w /aWorking/Zsh/Source/Source.zwc

The +X option is documented and means "load this now, but don't run it."


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

* Re: autoload
  2015-09-18 16:52                     ` autoload Bart Schaefer
@ 2015-09-18 18:29                       ` Ray Andrews
  2015-09-18 19:02                         ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-18 18:29 UTC (permalink / raw)
  To: zsh-users

On 09/18/2015 09:52 AM, Bart Schaefer wrote:
> } I see.  Nuts, there's nothing about that in the docs is there?
>
> There's an entire section for "Autoloading Functions" but it has no
> cross-reference from the "autoload" builtin (autoload points to
> functions points to typeset which finally does have the section
> reference).  I'll rearrange this a bit.
What would be sweet is a self-contained HOWTO sort of doc that walks you 
through the
entire subject with real world examples of solutions for real 
situations.  IOW, instead of
focusing on a command, it would focus on the goal: "Say you want your 
functions to
load faster.  Up till now you've been sourcing them at startup, which is 
fine, but
you can do much better ...."  ... 20 minutes latter you are cooking.
>
> }
> }      $ for aa in /aWorking/Zsh/Source/*; do source $aa; done
>
> You can do that:
>
> FPATH=/aWorking/Zsh/Source autoload +X -w /aWorking/Zsh/Source/Source.zwc
>
> The +X option is documented and means "load this now, but don't run it."
>
Ha!  Just when I'd decided to give up.


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

* Re: autoload
  2015-09-18 18:29                       ` autoload Ray Andrews
@ 2015-09-18 19:02                         ` Bart Schaefer
  2015-09-18 22:57                           ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-18 19:02 UTC (permalink / raw)
  To: zsh-users

On Sep 18, 11:29am, Ray Andrews wrote:
}
} What would be sweet is a self-contained HOWTO sort of doc that walks
} you through the entire subject with real world examples of solutions
} for real situations.

Yes, but there are an almost unlimited number of such possible HOWTO
topics and no volunteers who dedicate their time to writing this sort
of thing.

zcompile was even considered too obscure to get a mention in the
"From Bash to Zsh" book, though you'll find a lot of other HOWTO-type
stuff in there.


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

* Re: autoload
  2015-09-18 19:02                         ` autoload Bart Schaefer
@ 2015-09-18 22:57                           ` Ray Andrews
  0 siblings, 0 replies; 45+ messages in thread
From: Ray Andrews @ 2015-09-18 22:57 UTC (permalink / raw)
  To: zsh-users

On 09/18/2015 12:02 PM, Bart Schaefer wrote:
> On Sep 18, 11:29am, Ray Andrews wrote:
> }
> } What would be sweet is a self-contained HOWTO sort of doc that walks
> } you through the entire subject with real world examples of solutions
> } for real situations.
>
> Yes, but there are an almost unlimited number of such possible HOWTO
> topics and no volunteers who dedicate their time to writing this sort
> of thing.
I would if I ever mastered a topic.  Anyway I find most linux 
documentation to be
almost sadistically unhelpful. zsh's is already better than most.

BTW I just realized why I couldn't find "Autoloading
Functions" in zshmisc: because it's "AUTOLOADING FUNCTIONS"  and the 
search is
case sensitive :-(   It's the little things that drive ya nuts.


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

* Re: autoload
  2015-09-17 17:34 ` autoload Bart Schaefer
  2015-09-17 19:22   ` autoload Ray Andrews
@ 2015-09-19  0:14   ` Bart Schaefer
  2015-09-19 15:04     ` autoload Ray Andrews
  1 sibling, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-19  0:14 UTC (permalink / raw)
  To: Zsh Users

I decided I should clarify something:

On Sep 17, 10:34am, Bart Schaefer wrote:
}
} I think the problem here is that you've put a .zwc file IN a directory
} that is itself listed in $fpath.  This is typically a no-no.  You want
} a .zwc file to be treated as if it WERE a directory, NOT as if it were
} one of the function definition files IN the directory.

This is not quite correct.  I thought the situation was that we were
talking about was

    fpath=(/path/to/Directory ...)
    /path/to/Directory/Directory.zwc	# contains multiple functions

This would be wrong.  Instead it should be one of

    fpath=(/path/to/Directory ...)
    /path/to/Directory.zwc		# contains multiple functions
or
    fpath=(/path/to/Directory ...)
    /path/to/Directory/function.zwc	# contains one function only

In fact what Debian has done is the first of those two (correct) options,
so my "typically a no-no" was off base.

A third correct option would be

    fpath=(/path/to/Directory.zwc ...)

which I prefer, but which skips comparing the modification time of that
file to the files in /path/to/Directory/.  The advantage is that the
Directory itself need not exist, you can put the .zwc file anywhere.

Now, here's the interesting twist to what Debian has done.  They have

fpath=(... /usr/share/zsh/functions/Completion ...
       /usr/share/zsh/functions/Completion/Base ...)

with file /usr/share/zsh/functions/Completion/Base.zwc (among others).

For autoload, this is ambiguous -- if someone tries to run a command
named "Base", zsh searches /usr/share/zsh/functions/Completion/Base.zwc
for that function, because it might be the "one function only" option
described above.  It won't find the function there, of course, so it
will go on and look elsewhere and no one the wiser, and probably no one
ever runs "Base" anyway.

I don't want to claim there is anything wrong with Debian's choice, I
merly point it out as a probably-unintended side effect.


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

* Re: autoload
  2015-09-19  0:14   ` autoload Bart Schaefer
@ 2015-09-19 15:04     ` Ray Andrews
  2015-09-19 16:29       ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-19 15:04 UTC (permalink / raw)
  To: zsh-users

On 09/18/2015 05:14 PM, Bart Schaefer wrote:
> I decided I should clarify something:
>
...
> I don't want to claim there is anything wrong with Debian's choice, I
> merly point it out as a probably-unintended side effect.
>
If I understand, you are saying that a .zwc can't be in the same dir as 
the files from which it
was created?  Even though that is where it will be created?  I dunno, 
autoload/zcompile
seems like such a good idea but the implementation seems deliberately 
obscure.  As I read
the doc, it looked for the most recent file in whatever dir.  We have 
every possible twist
and turn, what we don't have is a simple and direct way of precompiling 
functions:

autoload --functions-out /All-My-Functions/All-My-Functions.zwc

... precompiled, *and/but* only loaded when called.  Exactly like 
sourcing, only faster and better.

Could even make making 'em look like this, just to be symetrical:

autoload --functions-in  /All-My-Functions/All-My-Functions.zwc 
/All-My-Functions/*

.... scripts, functions, however many per file, whatever the name ... no 
matter, it's all
wrapped up in the .zwc ready to go, just remembering that functions from 
scripts
will be 'auto-named' after the containing file.  Too cute?  Na ... it's 
easy to understand
and rather elegant.  The whole thing could be explained in two minutes
and implemented in 30 seconds.  Why do things *have* to be difficult?

As for me, I took Sebastian's stuff and converted it all to plain 
vanilla good old fashioned
righteous Protestant functions and may I never have to think about 
$fpath again ;-)
Seriously, I'll just let my brain cool down for a while and try to learn 
something
that a mortal can learn.  Sheesh, even Bart forgets how it works ...


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

* Re: autoload
  2015-09-19 15:04     ` autoload Ray Andrews
@ 2015-09-19 16:29       ` Bart Schaefer
  2015-09-19 18:13         ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-19 16:29 UTC (permalink / raw)
  To: zsh-users

On Sep 19,  8:04am, Ray Andrews wrote:
}
} If I understand, you are saying that a .zwc can't be in the same dir
} as the files from which it was created?

No.  I'm saying that if fpath is a tree, (X X/Y X/Y/Z), having
function files at all levels of the tree, then a file X/Y/Z.zwc
containing all the functions from Z might be wrongly interpreted
as containing a single function named Z instead.

} autoload --functions-out /All-My-Functions/All-My-Functions.zwc
} 
} autoload --functions-in  /All-My-Functions/All-My-Functions.zwc \
} /All-My-Functions/*

I don't understand your intended semantics of "out" and "in" here,
which argues against "expained in two minutes," but the point of
shell builtins is to provide building blocks for solutions like you
seem to be thinking of here.
 
} Sheesh, even Bart forgets how it works ...

Actually that's because I don't use it.  I'm nearly always either
running everything out of a development tree where I recompile zsh
(or pull new functions from git) sometimes multiple times a day,
or else running the same shell nonstop for weeks at a time without
ever restarting it.  There's no point in trying to keep a compiled 
bundle around if I'm never going to reference it.


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

* Re: autoload
  2015-09-19 16:29       ` autoload Bart Schaefer
@ 2015-09-19 18:13         ` Ray Andrews
  2015-09-19 21:22           ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-19 18:13 UTC (permalink / raw)
  To: zsh-users

On 09/19/2015 09:29 AM, Bart Schaefer wrote:
> On Sep 19,  8:04am, Ray Andrews wrote:
> }
>
> } autoload --functions-out /All-My-Functions/All-My-Functions.zwc
> }
> } autoload --functions-in  /All-My-Functions/All-My-Functions.zwc \
> } /All-My-Functions/*
>
> I don't understand your intended semantics of "out" and "in" here,
I'm thinking about how the creation of a zwc file, and it's subsequent 
use could
be considered to be part of the same builtin.  One being the 'inverse' 
of the other.

autoload --make-zwc /Functions/Functions.zwc /Functions/*
autoload --load-zwc /Functions/Functions.zwc

... it wouldn't take long to understand.


> Actually that's because I don't use it.
It's very relevant to what degree veterans like yourself use stuff. I'd 
provisionally
conclude that if you don't use it, then I don't want it.  There's more 
to be learned
from seeing how masters actually use a tool than from reading the tool's 
manual.
The book I'd long to read would be: "A *practical* guide to zsh".



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

* Re: autoload
  2015-09-19 18:13         ` autoload Ray Andrews
@ 2015-09-19 21:22           ` Bart Schaefer
  2015-09-19 22:12             ` autoload Ray Andrews
  2015-09-20  0:58             ` autoload Ray Andrews
  0 siblings, 2 replies; 45+ messages in thread
From: Bart Schaefer @ 2015-09-19 21:22 UTC (permalink / raw)
  To: zsh-users

On Sep 19, 11:13am, Ray Andrews wrote:
} Subject: Re: autoload
}
} I'm thinking about how the creation of a zwc file, and it's subsequent 
} use could be considered to be part of the same builtin.

But you don't say

    compiler -build something source/*
    compiler -load something

Rather, you build, and then you install, and then you run, and the way
all shells are designed, you use $path to bridge the install + run steps.

$fpath is the same idea; "autoload" is extra glue to tell the shell
that you DON'T want to use the default ($path) search for those names.

} autoload --make-zwc /Functions/Functions.zwc /Functions/*
} autoload --load-zwc /Functions/Functions.zwc
} 
} ... it wouldn't take long to understand.

As I've pointed out, these are exactly the same as

    zcompile /Functions/Functions.zwc /Functions/*
    FPATH=/Functions/Functions.zwc autoload +X -w /Functions/Functions.zwc

Although the better practice would be to do

    zcompile /Functions.zwc /Functions/*
    FPATH=/Functions.zwc autoload +X -w /Functions.zwc

if not because of the way fpath is searched, then for the same reason that
you shouldn't do

    tar -c /Functions/Functions.tar /Functions/*

Anyway, just make yourself a little wrapper function:

    loadorcompile() {	# rename as suits you
    	local how=$1; shift
	case $how in
	(--make-zwc) zcompile "$@";;
	(--load-zwd) FPATH=$1 autoload +X -w $1;;
	(*) print -u2 "don't know $how";;
	esac
    }

} It's very relevant to what degree veterans like yourself use stuff.
} I'd provisionally conclude that if you don't use it, then I don't
} want it.

As I tried to point out, I'm not a very typical user.  I would also
never use Sebastian's navigation tools, or anything from oh-my-zsh;
but that doesn't mean anyone else should avoid them.


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

* Re: autoload
  2015-09-19 21:22           ` autoload Bart Schaefer
@ 2015-09-19 22:12             ` Ray Andrews
  2015-09-20  5:53               ` autoload Bart Schaefer
  2015-09-20  0:58             ` autoload Ray Andrews
  1 sibling, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-19 22:12 UTC (permalink / raw)
  To: zsh-users

On 09/19/2015 02:22 PM, Bart Schaefer wrote:
> On Sep 19, 11:13am, Ray Andrews wrote:
> } Subject: Re: autoload
> }
> } I'm thinking about how the creation of a zwc file, and it's subsequent
> } use could be considered to be part of the same builtin.
>
> But you don't say
>
>      compiler -build something source/*
>      compiler -load something
>
> Rather, you build, and then you install, and then you run, and the way
> all shells are designed, you use $path to bridge the install + run steps.
Sure, it wasn't to be taken very seriously, I'm just thinking about the 
idea that there
could be a sort of symmetry between creating a .zwc and then loading 
one--you
could think of them as so related that the command name could be the 
same.  IOW
the creation of a .zwc presupposes subsequent use of it the same way 
that making
dinner supposes eating dinner.  Command recall would be easier ... but 
that's
never going to happen.  I guess the parallel would be 'zip' vs. 
'unzip'--we're glad
that the names are related.

> As I've pointed out, these are exactly the same as
>
>      zcompile /Functions/Functions.zwc /Functions/*
>      FPATH=/Functions/Functions.zwc autoload +X -w /Functions/Functions.zwc
>
> Although the better practice would be to do
>
>      zcompile /Functions.zwc /Functions/*
>      FPATH=/Functions.zwc autoload +X -w /Functions.zwc
But ... well, let me try it again, I may have busted something.
> } It's very relevant to what degree veterans like yourself use stuff.
> } I'd provisionally conclude that if you don't use it, then I don't
> } want it.
>
> As I tried to point out, I'm not a very typical user.  I would also
> never use Sebastian's navigation tools, or anything from oh-my-zsh;
> but that doesn't mean anyone else should avoid them.
No, OTOH in my judgment typicality is not of great value whereas decades of
experience is.  Not that I have the slightest hesitation in doing things 
my own
way, but I always want to know what the Old Masters think even if I 
choose to
differ ... until learning better.
>


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

* Re: autoload
  2015-09-19 21:22           ` autoload Bart Schaefer
  2015-09-19 22:12             ` autoload Ray Andrews
@ 2015-09-20  0:58             ` Ray Andrews
  2015-09-20  5:41               ` autoload Bart Schaefer
  1 sibling, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-20  0:58 UTC (permalink / raw)
  To: zsh-users

On 09/19/2015 02:22 PM, Bart Schaefer wrote:
> As I've pointed out, these are exactly the same as
>
>      zcompile /Functions/Functions.zwc /Functions/*
>      FPATH=/Functions/Functions.zwc autoload +X -w /Functions/Functions.zwc
>
> Although the better practice would be to do
>
>      zcompile /Functions.zwc /Functions/*
>      FPATH=/Functions.zwc autoload +X -w /Functions.zwc

By gum it works if you get it exactly right:

-"zcompile ... (N-.:t)" ... or it barfs if there's a directory on the 
same path. Fussy fussy.
-"autoload +X -w ..." works with Sebastian's, but not with mine (which 
are all functions).
-"autoload -w ..." works with mine but not Sebastian's.
-"source miscfunctions" *before* calling an autoloaded function to have 
it work the first time.
-Append new dirs to FPATH or other things break.

> if not because of the way fpath is searched, then for the same reason that
> you shouldn't do
>
>      tar -c /Functions/Functions.tar /Functions/*
... and most importantly, follow this advice, or if you rerun zcompile 
where there's already a
.zwc, it rather dumbly tries to eat it's own tail and build itself into 
itself and nothing works.

I guess the zcompile of my dreams would be able to process both scripts 
and functions in one
go, and be able to see the functions in 'miscfunctions' regardless of 
the filename, and not
try to digest existing .zwc's, and not worry about directories. And the 
autoload of my dreams
would be able to pass all of it back every time.  Best to leave it to 
zsh internals it's too
fragile for anything else.  Apologies to the list for all this.




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

* Re: autoload
  2015-09-20  0:58             ` autoload Ray Andrews
@ 2015-09-20  5:41               ` Bart Schaefer
  2015-09-20 23:21                 ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-20  5:41 UTC (permalink / raw)
  To: zsh-users

On Sep 19,  5:58pm, Ray Andrews wrote:
}
} By gum it works if you get it exactly right:
} 
} -"zcompile ... (N-.:t)" ... or it barfs if there's a directory on the 
} same path. Fussy fussy.

You *really* don't want that :t in there.

} -"autoload +X -w ..." works with Sebastian's, but not with mine (which 
} are all functions).

This is either because (a) you needed "zcompile -k ..." with yours, or
(b) you have multiple functions per file, which we've already discussed
at length with respect to autoload.  [More on this below.]

} -"autoload -w ..." works with mine but not Sebastian's.

I think "autoload" is entirely superfluous in this case, because:

} -"source miscfunctions" *before* calling an autoloaded function to have 
} it work the first time.

Er, no.  In that case it's 99% certain the function isn't autoloaded at
all, rather it's simply been fully defined during the "source" command.
The "source" command is probably reading miscfunctions.zwc, though.

} -Append new dirs to FPATH or other things break.

I have no idea whether that means "the FPATH has to contain some new
stuff" or also "... and the new stuff has to go at the end, it can't
be put anywhere else".  Either could be true or false depending on the
context.

} I guess the zcompile of my dreams would be able to process both
} scripts and functions in one go

This has nothing to do with zcompile output and everything to do with
how the result is read back.  Scripts you want to "source ..." and
functions you want to define (and possibly also call, if defining is
happening as part of deferred loading).

(Maybe we should never have created the "autoload" command, because
that name just muddles up the act of creating a placeholder for
deferred loading with the actual deferred loading event itself.)

[I just noticed that the doc for zcompile refers to "execution of
scripts".  This is misleading, it should say "sourcing of scripts".
Execution (as in spawning a new shell to run a file that has execute
mode bit set) does not involve loading .zwc files; only "source"
and "." do that.]

Also zcompile has no way to guess if the file it's being used on is a
source-able script or a function body.  You'd need to tell it which,
somehow.  So "all in one go" would become some convoluted thing like

zcompileOfMyDreams --script=miscfunctions --function=n-list ...

} and be able to see the functions in 'miscfunctions' regardless of
} the filename

This is for all practical purposes impossible to do automatically.
In order to know what functions are in "miscfunctions", zcompile
would have to first *run* (source) that file, which might have
other side effects besides just defining the functions themselves.

Neverthe less zcompile does have a way to do what you're asking,
assuming you know there are no side-effects:

    ( # subshell so as not to muck up the parent
      unfunction -m \*		# clean out all extra functions
      source miscfunctions	# load the functions we care about
      zcompile -a -c miscfunctions.zwc	# compile all the functions
    )

Note that here you are explicitly doing the "run that file" step.

} and not try to digest existing .zwc's,
} and not worry about directories.

This is a philosophical issue along the same lines as CSH_NULL_GLOB.
If I name a bunch of things and some of them are wrong, should the
shell complain about them or not, and either way, should it skip
them and continue working on the ones that are correct?  Which is
more likely to produce the final result that the user expected?

Since the user is perfectly capable of filtering these out when the
argument list is built, I think the decision to complain and stop
is the correct one.

} And the autoload of my dreams would be able to pass all of it back
} every time.

Maybe if you try replacing "autoload" with its synonym "functions -u"
(create an undefined function) in your mental map, you'd get a better
idea of what you're asking.

What would it mean to create an undefined script?  What event would
cause it to become defined?


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

* Re: autoload
  2015-09-19 22:12             ` autoload Ray Andrews
@ 2015-09-20  5:53               ` Bart Schaefer
  2015-09-20 15:37                 ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-20  5:53 UTC (permalink / raw)
  To: zsh-users

On Sep 19,  3:12pm, Ray Andrews wrote:
}
} the creation of a .zwc presupposes subsequent use of it the same way 
} that making dinner supposes eating dinner.

Obviously you've never worked in a restaurant.

} I guess the parallel would be 'zip' vs.  'unzip'--we're glad
} that the names are related.

But that's not a parallel at all, because unzip doesn't do anything
with the data that it unpacks.  A better parallel might be, creating
a DVD vs. playing it back.


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

* Re: autoload
  2015-09-20  5:53               ` autoload Bart Schaefer
@ 2015-09-20 15:37                 ` Ray Andrews
  2015-09-20 15:59                   ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-20 15:37 UTC (permalink / raw)
  To: zsh-users

On 09/19/2015 10:53 PM, Bart Schaefer wrote:
> On Sep 19,  3:12pm, Ray Andrews wrote:
> }
> } the creation of a .zwc presupposes subsequent use of it the same way
> } that making dinner supposes eating dinner.
>
> Obviously you've never worked in a restaurant.
>
> } I guess the parallel would be 'zip' vs.  'unzip'--we're glad
> } that the names are related.
>
> But that's not a parallel at all, because unzip doesn't do anything
> with the data that it unpacks.  A better parallel might be, creating
> a DVD vs. playing it back.
>
It's of philosophical interest onlybut this kind of question engages me 
quite a bit.
Your example of 'compiler --run-program' certainly demonstrates the 
reducto ad
absurdum of the idea--but one might compile something with a dozen different
compilers and compilers might compile any one of thousands of different 
programs,
and the compilers certainly don't care what the program does, and the 
program
might run under a dozen different OSon any compatible machine--
so their is no 'tight' link. Same with a DVD--one might burn with any 
one of several
programs and play back with any one of several with no link between the 
creator
and the player, and the contents of the product--the DVD--is irrelevant 
to the burner
and to the player.  (So long as the standards are maintained, of course.)

OTOH zcompile produces a filespecifically and only
usable by autoload, so one might rightly think of zcompile as a subsidiary
program to autoload.  I doubt you could change one without considering the
effect on the other. I'd say it's the same with zip/unzip--if one 
changes then
the other must change--they are a suite of linked programs. But whereas
unzip does not 'use' the content of whatever it unzips, autoload uses
a .zwc file and is the only program that does. Thusly, a mnemonic similarity
between names would be very mildly usefulthe same way that 'unzip'
is usefully similar to 'zip'.  In the real world of course, renaming 
zcompile
would do far more harm than good, so it's an academic discussion. Had
I been around 20 years ago, I'd have suggested naming it 'makezwc' or
something like that, or 'autoload --makezwc' or some such. One is given
a tiny but friendly hint that things are related, that's all. But unix 
is not
a friendly placeand seems not to want to be.  It delights in its obscurity.


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

* Re: autoload
  2015-09-20 15:37                 ` autoload Ray Andrews
@ 2015-09-20 15:59                   ` Bart Schaefer
  0 siblings, 0 replies; 45+ messages in thread
From: Bart Schaefer @ 2015-09-20 15:59 UTC (permalink / raw)
  To: zsh-users

On Sep 20,  8:37am, Ray Andrews wrote:
}
} OTOH zcompile produces a filespecifically and only
} usable by autoload

No, that's not true:  zcompiled files may be used by either autoload
(strictly speaking, by the deferred-loading procedure that USUALLY
happens long after the autoload command has been run) OR by source,
and the semantics of the two are not the same.

-- 
Barton E. Schaefer


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

* Re: autoload
  2015-09-20  5:41               ` autoload Bart Schaefer
@ 2015-09-20 23:21                 ` Ray Andrews
  2015-09-21  4:18                   ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-20 23:21 UTC (permalink / raw)
  To: zsh-users

On 09/19/2015 10:41 PM, Bart Schaefer wrote:
> } -"zcompile ... (N-.:t)" ... or it barfs if there's a directory on the
> } same path. Fussy fussy.
>
> You *really* don't want that :t in there.

Yup.  It turns out that it was the regular versions of the functions 
that were being found.
> This is for all practical purposes impossible to do automatically.

Sure, I can't argue, you know how it works.  My dream of simplicity may 
indeed
be impossible.  But you know what's in my head--something that's the 
equivalent of
'just sourcing' your functions, but doing it from precompiled code, and 
not pre-loading
anything at all, but doing it only when the function is actually 
called.  Nuts, it's so
elegant in theory.  I'm sorta in love with the idea but implementation 
becomes
a can of worms.
> } and not try to digest existing .zwc's,
> } and not worry about directories.
>
> This is a philosophical issue along the same lines as CSH_NULL_GLOB.
> If I name a bunch of things and some of them are wrong, should the
> shell complain about them or not, and either way, should it skip
> them and continue working on the ones that are correct?  Which is
> more likely to produce the final result that the user expected?
Indeed, and the right answer is not obvious.  Hand holding tends to end up
creating more problems that it solves.  I'd suppose that if there are 
built in
exceptions to the plain reading of a command it must be exceptions that
could never be desired ever, like, perhaps, including a .zwc inside it's own
replacement. Or not.  I always hated Microsoft for making 80% of things
easier and the remaining 20% impossible.  If it has to be tough, then it has
to be tough.

You know Bart, with all the time you've spent on this, you could have 
written
that HOWTO ;-)

Seriously, it requires something broader than just reading the manual.
>


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

* Re: autoload
  2015-09-20 23:21                 ` autoload Ray Andrews
@ 2015-09-21  4:18                   ` Bart Schaefer
  2015-09-21 17:03                     ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-21  4:18 UTC (permalink / raw)
  To: zsh-users

On Sep 20,  4:21pm, Ray Andrews wrote:
}
} But you know what's in my head--something that's the equivalent of
} 'just sourcing' your functions, but doing it from precompiled code,
} and not pre-loading anything at all, but doing it only when the
} function is actually called.

Except for the point that "just sourcing" doesn't actually call the
function, everything you wrote is what DOES happen as long as the
functions are defined in separate files.  Because the language is
interpreted, the shell itself can't decompose a file into individual
function entry points the way e.g. a linker can for a shared object.
Requiring the file basename to be the same as the entry point name is
the most obvious way to handle this.

} You know Bart, with all the time you've spent on this, you could have 
} written that HOWTO ;-)

The problem is, I wouldn't have known what to write.


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

* Re: autoload
  2015-09-21  4:18                   ` autoload Bart Schaefer
@ 2015-09-21 17:03                     ` Ray Andrews
  2015-09-21 18:17                       ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-21 17:03 UTC (permalink / raw)
  To: zsh-users

On 09/20/2015 09:18 PM, Bart Schaefer wrote:
> Except for the point that "just sourcing" doesn't actually call the
> function, everything you wrote is what DOES happen as long as the
> functions are defined in separate files.  Because the language is
> interpreted, the shell itself can't decompose a file into individual
> function entry points the way e.g. a linker can for a shared object.
Really?  That's hard to fathom.  I source a file and it finds whatever 
functions may
be in there, but they can't be packed into a .zwc file without worrying 
about it's
name?  I'll take that on authority, but it blows my breakers.  I'd have 
thought it
would be as transparent as:

     for aa in /aWorking/Zsh/Source/*; do source $aa; done

... becoming:

zcompile --do_it  /not-the-same-directory-dummy\!/Source.zwc 
/aWorking/Zsh/Source/*

... but if you say that's not even doable I can't argue.
> } You know Bart, with all the time you've spent on this, you could have
> } written that HOWTO ;-)
>
> The problem is, I wouldn't have known what to write.
>
Yeah, the paradox of the expert.  Experts don't know what they know.  
The best
writer is the guy who just learned it so he remembers what he needed to 
learn,
where he went wrong, what was important, what was distraction.  Then the
expert edits it for factuality.  Once four or five learners have added their
lessons to the doc, it becomes really usable for the next guy.  Like the 
best
wikis.  The less of an expert you are, the better judge you are as to the
usefulness of a doc.


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

* Re: autoload
  2015-09-21 17:03                     ` autoload Ray Andrews
@ 2015-09-21 18:17                       ` Bart Schaefer
  2015-09-21 20:09                         ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-21 18:17 UTC (permalink / raw)
  To: zsh-users

On Sep 21, 10:03am, Ray Andrews wrote:
} Subject: Re: autoload
}
} On 09/20/2015 09:18 PM, Bart Schaefer wrote:
} > Because the language is
} > interpreted, the shell itself can't decompose a file into individual
} > function entry points the way e.g. a linker can for a shared object.
} 
} Really? That's hard to fathom. I source a file and it finds whatever
} functions may be in there, but they can't be packed into a .zwc file
} without worrying about it's name?

Did you miss the email where I explained how to do that?

} I'd have thought it would be as transparent as:
} 
} zcompile --do_it  /not-the-same-directory-dummy\!/Source.zwc 
} /aWorking/Zsh/Source/*

Really think about "because the language is interpreted."

Suppose I have

    typeset some_critical_var_used_by_foo_and_bar=really_important_value

    foo() { ... }
    bar() { ... }

Now I want to compile this.  Sure, the shell could dump out foo and bar,
but where does it put that typeset?  Does it evaluate the assignment at
compile time?  (A C compiler would, but that's typically the wrong
semantics for a shell.)

What if really_important_value absolutely must only be interpreted once,
not each time foo and bar are individually loaded?

What if the names "foo" and "bar" are actually stored in other variables?

    function $foo { ... }

What if there's an "if" structure?

    if some_runtime_test
    then
	foo() { ... }
	bar() { ... }
    else
        bar() { ... }
	foo() { ... }
    fi

What if there's a runtime test with that crucial typeset INSIDE the test?

I can make up an infinite number of increasingly convoluted cases to
break any "simple, elegant" automation.  So unless you happen to have
"zmodload zsh/artificial-intellgence" lying around ready for use, I'm
done with this discussion.


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

* Re: autoload
  2015-09-21 18:17                       ` autoload Bart Schaefer
@ 2015-09-21 20:09                         ` Ray Andrews
  2015-09-22  3:19                           ` autoload Bart Schaefer
  0 siblings, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-21 20:09 UTC (permalink / raw)
  To: zsh-users

On 09/21/2015 11:17 AM, Bart Schaefer wrote:
> Did you miss the email where I explained how to do that?
On the first pass through a subject like this there is so much to learn
and so much error and misunderstanding and diversions and distractions
that one is lucky to come out of it alive.  On the second pass things will
gel.
>
> Really think about "because the language is interpreted."
Deep lessons ...
>
> I can make up an infinite number of increasingly convoluted cases to
> break any "simple, elegant" automation.  So unless you happen to have
> "zmodload zsh/artificial-intellgence" lying around ready for use, I'm
> done with this discussion.
>
I'd just expect the precompiled function to behave exactly as a sourced 
function
would behave, all that's different is that the file being parsed is ... 
is this where
I go off the rails? ... what I'd call 'object code' which is to say that 
it's somewhat
pre-digested as far as the interpreter goes.  But when it is actually 
called (as if
it were sourced) it would behave exactly identically to a normal sourced 
function.
It's just parsed quicker.  Very different from C, as you say.

I dunno, if I have a function ' test () { echo $PWD } ' I'm not 
expecting $PWD to
be hard captured at sourcing time, is there even a way to do that? It 
might be
cool if there was a way, but surely that's rather unusual.  So, on the 
contrary,
I'm thinking not of artificial-intelligence but rather of something
dumb as a donkey.  Autoloaded functions at present seem to behave as I'd
expect, so I don't know where the problem arises.  Your 'evaluate once'
scenario is valid of course, but I have no idea how that would be 
handled even
by a regular function.  It seems a separate issue to me.

To be honest, your stamina sticking with this so long has already 
astonished me,
so if you're done, that's overdue, but thanks.


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

* Re: autoload
  2015-09-21 20:09                         ` autoload Ray Andrews
@ 2015-09-22  3:19                           ` Bart Schaefer
  2015-09-22 17:33                             ` autoload Ray Andrews
  2015-09-29 23:16                             ` wheels within wheels Ray Andrews
  0 siblings, 2 replies; 45+ messages in thread
From: Bart Schaefer @ 2015-09-22  3:19 UTC (permalink / raw)
  To: zsh-users

OK, one last.

On Sep 21,  1:09pm, Ray Andrews wrote:
}
} I'd just expect the precompiled function to behave exactly as a
} sourced function would behave, all that's different is that the file
} being parsed is ... is this where I go off the rails?

Yes.

You're not asking for a precompiled function to act like a sourced
function.  A sourced function, to the extent that means anything at all,
does nothing but become defined.  But "sourcing" a function (which you
actually can't do, you can only source a *file*) and "calling" a
function are two completely distinct things.  Rather, you ask for
compiling a whole file full of defined functions, to behave like
creating a bunch of undefined ones.

An undefined function (created with "functions -u" aka autoload) does
both of the source and call operations, but it only knows the one name
(its own).  So the file (to be sourced) and the function (to be called)
both have to be identified by that single name.

Could we have created an entire distinct data structure that stores
both a file name and a function name, and means "oh by the way, when
you try to run foo, you actually have to go read the file bar" ?
Yes, we could.  We didn't.  We re-used the existing data structure
of a function, because one field for the name seemed like enough,
and the path-search mechanism seemed like a good existing model for
finding the file.

Further, the point of autoloading was to read into memory exactly
those functions that are actually used.  If to get foo you have to
source bar and do everything bar contains, you may end up reading
(and storing) a hundred functions in order to call one of them.
Not what we wanted to encourage.  So, one function per file.

zcompile lets you do two things:  compile a single file to be read by
source (*) or pack multiple files into an archive to be processed
by autoload.  But the latter doesn't change the fact that autoload
needs to match one file (one thing packed in the archive) to one
function name.  And the former doesn't magically grant the ability
to explode the single file into multiple archive entries. (**)

(*) But this is constrained in that both the original file and the
compiled file have to exist size-by-side, so that source can choose
the newer of the two.  This constraint isn't strictly necessary.

(**) "zcompile -c" can explode functions that are already in memory
into multiple "files" that then go into the archive, but that's as
close as it gets.


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

* Re: autoload
  2015-09-22  3:19                           ` autoload Bart Schaefer
@ 2015-09-22 17:33                             ` Ray Andrews
  2015-09-23  4:39                               ` autoload Bart Schaefer
  2015-09-29 23:16                             ` wheels within wheels Ray Andrews
  1 sibling, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-22 17:33 UTC (permalink / raw)
  To: zsh-users

On 09/21/2015 08:19 PM, Bart Schaefer wrote:
> You're not asking for a precompiled function to act like a sourced
> function.  A sourced function, to the extent that means anything at all,
> does nothing but become defined.  But "sourcing" a function (which you
> actually can't do, you can only source a *file*) and "calling" a
> function are two completely distinct things.
I understand, I just chose the wrong word.
>    Rather, you ask for
> compiling a whole file full of defined functions, to behave like
> creating a bunch of undefined ones.
>
> An undefined function (created with "functions -u" aka autoload) does
> both of the source and call operations, but it only knows the one name
> (its own).  So the file (to be sourced) and the function (to be called)
> both have to be identified by that single name.
>
> Could we have created an entire distinct data structure that stores
> both a file name and a function name, and means "oh by the way, when
> you try to run foo, you actually have to go read the file bar" ?
> Yes, we could.  We didn't.  We re-used the existing data structure
> of a function, because one field for the name seemed like enough,
> and the path-search mechanism seemed like a good existing model for
> finding the file.
Ok.  I admit that my notion does presume a table linking functions with 
their
.zwc:

raysfunc    /directory/raysfunc.zwc    line1
somefunc  /directory/all/allfunc.zwc  line40
otherfunc  /directory/all/allfunc.zwc  line200
...

I get a glimpse of how you did what you did within existing structures. 
If I understood
that fully I'd grok the limitations of the system.  I guess it's a bit 
outrageous of me,
but I presumed that in the hash table that links functions to where ever 
they are,
a sort of pointer to a line in a .zwc file would not be a huge problem.
>
> Further, the point of autoloading was to read into memory exactly
> those functions that are actually used.  If to get foo you have to
> source bar and do everything bar contains, you may end up reading
> (and storing) a hundred functions in order to call one of them.
> Not what we wanted to encourage.  So, one function per file.

That is so insightful, cuz I had exactly the opposite as the supposed 
goal--to
have functions available but not sourced *just in case* you might need them.
I never understood:

     autoload -U colors && colors

... because I'm thinking to myself: 'Why would you 'autoload' something 
that
you are just going to plain vanilla load anyway? Why not just load it 
and be
done with it?' (It doesn't work with compinit.  It seems because 
compinit will
be looking on FPATH for the rest of itself autoloaded, so it's committed to
that method--but you understand my thought.)
>
> zcompile lets you do two things:  compile a single file to be read by
> source (*) or pack multiple files into an archive to be processed
> by autoload.  But the latter doesn't change the fact that autoload
> needs to match one file (one thing packed in the archive) to one
> function name.

But ... if we have several functions packed in one .zwc it is not 
logically possible
for the name of the file to match the name of more than one of the 
functions which
breaks my head as far as this one-to-one function-file thing.  You tell 
me that
there is this function name - file name requirement but then violate that
commandment by packing in several functions to one .zwc.  I get that if 
a script
is autoloaded it will/must be 'named' after the file it came from. One 
script!
But with functions?  The rule is not followed.

> And the former doesn't magically grant the ability
> to explode the single file into multiple archive entries. (**)
>
> (*) But this is constrained in that both the original file and the
> compiled file have to exist size-by-side, so that source can choose
> the newer of the two.  This constraint isn't strictly necessary.
Well therewego.  Previously you're saying that these .zwc should not be 
in the same
dir, now they should be in the same dir. Nuts, they are created in the 
same dir.  I
tested that by touching the files--as you say, it finds the newest. But 
then you tell
me that best practice is to move the thing :-(  And, speaking of 
philosophy, here
is a case of hand-holding.  The first command found on the path is the 
one used,
and too bad for you if a newer version exists somewhere lower down. It 
doesn't
scan the whole path and load the newest file.  I'm expecting that if I 
autoload
something then it's active and too bad if there's a newer file:

     $ autoload my_function
     $ source /functions/myfunction

... I get the sourced version.

     $ source /functions/myfunction
     $ autoload my_function

... I get the version in the .zwc  found on FPATH.  If I want the newer 
version
then I should source it.

>
> (**) "zcompile -c" can explode functions that are already in memory
> into multiple "files" that then go into the archive, but that's as
> close as it gets.
>
When I revisit this, I'll read your posts backwards.  This one is the 
one that would come first
in the HOWTO.  The first thing to understand is why, when and where we'd 
want to
use autoload.  What is it for?  Why did God make it on the seventh day?  
Then, it's
constraints and why they are what they are, then the implementation with 
examples.

Looking back, I've misunderstood the whole point of the thing.  Like the 
C-head
that I am, I'm thinking: 'What a good idea!  We can boil down our 
functions to
'.obj' files for faster loading, pack them together into one file for 
more speed yet, and
best of all, have them unloaded in memory until they are actually called 
at which time
they are 'autoloaded' automagically.  How elegant, I says to myself, 
it's like a .zip--all
compressed and packed together, and just as you can extract a single 
file from a .zip
so you can source a single function from a .zwc and zsh will even do it 
automatically
for you if you autoload that function cuz zsh will keep a table of where 
that
function is found and source it only when you call for the function.

It's all Sebastian's fault ;-)

Seriously sir, I exhaust your patience.  For now the one thing I know is 
that I don't
want to autoload anything, it's too obscure.


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

* Re: autoload
  2015-09-22 17:33                             ` autoload Ray Andrews
@ 2015-09-23  4:39                               ` Bart Schaefer
  2015-09-23 15:06                                 ` autoload Ray Andrews
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-23  4:39 UTC (permalink / raw)
  To: zsh-users

Just so no one else is confused ...

On Sep 22, 10:33am, Ray Andrews wrote:
}
} > zcompile lets you do two things:  compile a single file to be read by
} > source (*) or pack multiple files into an archive to be processed
} > by autoload.
} >
} > (*) But this is constrained in that both the original file and the
} > compiled file have to exist size-by-side, so that source can choose
} > the newer of the two.  This constraint isn't strictly necessary.
} 
} Well therewego.  Previously you're saying that these .zwc should not be
} in the same dir, now they should be in the same dir.

Two different use cases:

(1) Packing up multiple files into a composite ZWC?  Don't put the
    composite alongside the files packed in it.  This is the case we
    started out talking about two dozen messages ago.  Makes sense
    only for autoload.

(2) Packing one file into one correspondingly-named ZWC?  Put the ZWC
    alongside the origin file.  Works for source or autoload, but in
    the autoload case this must be one-function/one-file/same-name.

The autoload search is straightforward:  $fpath order comes first.
If, while searching fpath in order, a pair of files "x" and "x.zwc"
is found, read the newer one.  As a special case of this, if "x" is
actually a directory listed in fpath, assume "x.zwc" contains all the
same files as "x/".

The "source" (and ".") search rule is similar, except using $path and
without the directory special case.

}      $ autoload my_function
}      $ source /functions/myfunction
} 
} ... I get the sourced version.

Yes, because in this case you clobbered the autoload declaration by
loading the full function definition on top of it with "source".

}      $ source /functions/myfunction
}      $ autoload my_function
} 
} ... I get the version in the .zwc found on FPATH.

No, you still get the one from the "source" command, because autoload
won't replace an existing function definition.  The only way to ever
get the version found on fpath is by never doing the "source" at all.


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

* Re: autoload
  2015-09-23  4:39                               ` autoload Bart Schaefer
@ 2015-09-23 15:06                                 ` Ray Andrews
  0 siblings, 0 replies; 45+ messages in thread
From: Ray Andrews @ 2015-09-23 15:06 UTC (permalink / raw)
  To: zsh-users

On 09/22/2015 09:39 PM, Bart Schaefer wrote:
> Just so no one else is confused ...
>
>
Indeed.  But 3/4 of what we've discussed is not documented so others might
very well be unsure of these things too.  I did really jump to 
conclusions as
to how the thing would work, and I'm guilty of wishful thinking as always.
Still I do wish this thread could be gelled into even the outline of a 
howto
sort of doc. that way it would have served some purpose.  It seems one must
understand autoload from it's roots.


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

* wheels within wheels
  2015-09-22  3:19                           ` autoload Bart Schaefer
  2015-09-22 17:33                             ` autoload Ray Andrews
@ 2015-09-29 23:16                             ` Ray Andrews
  2015-09-30  2:55                               ` Kurtis Rader
  1 sibling, 1 reply; 45+ messages in thread
From: Ray Andrews @ 2015-09-29 23:16 UTC (permalink / raw)
  To: zsh-users

I just learned that it's possible to declare a function within another 
function.  A strange liberty.  Why would one want to, and what are the 
gotchas of doing so?

BTW Bart, any further word on where to find the latest manual?  When we 
were hacking over autoload I'd have liked reading those edits you made 
hot of the press.  Is this  a 'git' sort of thing?


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

* Re: wheels within wheels
  2015-09-29 23:16                             ` wheels within wheels Ray Andrews
@ 2015-09-30  2:55                               ` Kurtis Rader
  2015-09-30  3:24                                 ` Ray Andrews
  2015-09-30  3:40                                 ` Bart Schaefer
  0 siblings, 2 replies; 45+ messages in thread
From: Kurtis Rader @ 2015-09-30  2:55 UTC (permalink / raw)
  To: Ray Andrews; +Cc: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 1599 bytes --]

On Tue, Sep 29, 2015 at 4:16 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:

> I just learned that it's possible to declare a function within another
> function.  A strange liberty.  Why would one want to, and what are the
> gotchas of doing so?
>

Many compiled languages support the concept of "closures". Even those, like
Python, which are compiled on the fly into byte-code as they are executed.
On the other hand zsh, and in general any shell, based on bash or csh do
not support closures or namespaces so I have no idea why someone would nest
function definitions in those shell languages. Google "zsh closures" and
read this answer:

http://unix.stackexchange.com/questions/94129/is-there-something-like-closures-for-zsh


In short: don't do it. You can see for yourself that nested, named,
function definitions are in fact globally visible (as opposed to visible
only to the function in which they're defined) by executing the following
script. Anonymous functions defined within another function are a different
matter but outside the scope of this question.

I've seen some pretty amazing bash/csh/ksh/zsh scripts in my life.
Including one that implemented an assembly language compiler. But if you
need that level of complexity you should be using a different language. If
the only tool you know how to use is a hammer then every problem looks like
a nail.

#!/bin/zsh

function foo {
    function bar {
        echo hello from bar
    }

    echo hello from foo
    bar
}

echo calling foo
foo
echo calling bar
bar

-- 
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

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

* Re: wheels within wheels
  2015-09-30  2:55                               ` Kurtis Rader
@ 2015-09-30  3:24                                 ` Ray Andrews
  2015-09-30  3:40                                 ` Bart Schaefer
  1 sibling, 0 replies; 45+ messages in thread
From: Ray Andrews @ 2015-09-30  3:24 UTC (permalink / raw)
  To: zsh-users

On 09/29/2015 07:55 PM, Kurtis Rader wrote:
> http://unix.stackexchange.com/questions/94129/is-there-something-like-closures-for-zsh
Never heard of it.  But thanks for the link.  I forget that shells 
aren't 'real' languages.
Nuts, I'm even getting used to not declaring variables.  As Bart once 
said, shells are
a glue for various command line operations.

> In short: don't do it.

I wouldn't, unless there was some sort of wonderful reason to, which is 
what I'm asking.

> You can see for yourself that nested, named,
> function definitions are in fact globally visible (as opposed to visible
> only to the function in which they're defined) by executing the following
> script. Anonymous functions defined within another function are a different
> matter but outside the scope of this question.

Yeah, I ran my own tests and it seems so.  One might think that this 
would be some sort of
localization mechanism, but it seems not to be the case.  Ok, thanks 
Kurtis, I'll not
try any such thing.  It seems very strange that it's even legal.


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

* Re: wheels within wheels
  2015-09-30  2:55                               ` Kurtis Rader
  2015-09-30  3:24                                 ` Ray Andrews
@ 2015-09-30  3:40                                 ` Bart Schaefer
  2015-09-30  4:03                                   ` Mikael Magnusson
  2015-09-30  4:15                                   ` Ray Andrews
  1 sibling, 2 replies; 45+ messages in thread
From: Bart Schaefer @ 2015-09-30  3:40 UTC (permalink / raw)
  To: zsh-users

On Sep 29,  4:16pm, Ray Andrews wrote:
} Subject: wheels within wheels
}
} I just learned that it's possible to declare a function within another 
} function.  A strange liberty.

Interpreted language.  Defining a function is just like executing any
other command, so you can do it anywhere a command is allowed.  There
really isn't any such thing as "declaring" a function -- either it is
defined [the command that defines it has been *executed*, not merely
written out as part of some dormant code] or it isn't.

The "functions -u" aka "autoload" command is the closest there is to
"declaring" a function, but really it defines a function with an empty
body which is to be filled in later.  This is inaccurately referred to
as an "undefined" function because that's shorter to say.

} Why would one want to, and what are the gotchas of doing so?

Consider it a sort of conditional compilation, if you need a comparison.
Like the _git and tetris examples in the autoload thread -- various
helper functions get defined only if/when the main function that needs
them is actually called.

In addition to what Kurtis says, a gotcha with nesting functions is
that every time the outer function is called, it re-defines the inner
functions (deletes the old definitions and re-create them).  Remember,
interpreted language.  Everything interesting happens at run time.

Therefore do not nest function definitions unless you understand very
well what they are doing.

} BTW Bart, any further word on where to find the latest manual?

You should use the manual for the version of zsh that you have.  If you
start looking at the latest manual but you're not using the latest
shell, you may get just as much misinformation as if you're looking at
an older manual.

} hot of the press.  Is this  a 'git' sort of thing?

Yes.

On Sep 29,  7:55pm, Kurtis Rader wrote:
}
} In short: don't do it.

That's a bit too short.  Nesting function definitions is exactly what a
lot of autoloadable functions do.  The difference is that autoloadable
functions also redefine *themselves* this way, to change what happens
the second time the "same" function (in name only) is called.

} You can see for yourself that nested, named,
} function definitions are in fact globally visible (as opposed to visible
} only to the function in which they're defined) by executing the following
} script.

Here's a modification of that script:

    function foo {
      echo defining bar
      function bar {
	echo hello from bar
      }
      echo redefining foo
      function foo {
	echo hello from new foo
	bar
      }
      # this looks like infinite recursion,
      # but it is not, because foo was redefined
      foo
    }

    # This will say "command not found"
    echo calling bar before foo
    bar
    echo calling foo
    foo
    echo calling bar after foo
    bar
    echo calling foo again
    foo


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

* Re: wheels within wheels
  2015-09-30  3:40                                 ` Bart Schaefer
@ 2015-09-30  4:03                                   ` Mikael Magnusson
  2015-09-30  4:15                                   ` Ray Andrews
  1 sibling, 0 replies; 45+ messages in thread
From: Mikael Magnusson @ 2015-09-30  4:03 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On Wed, Sep 30, 2015 at 5:40 AM, Bart Schaefer
<schaefer@brasslantern.com> wrote:
> On Sep 29,  7:55pm, Kurtis Rader wrote:
> }
> } In short: don't do it.
>
> That's a bit too short.  Nesting function definitions is exactly what a
> lot of autoloadable functions do.  The difference is that autoloadable
> functions also redefine *themselves* this way, to change what happens
> the second time the "same" function (in name only) is called.

Another example where this is needed is to do this:

function _zle_line_init() {
  zle set-local-history -n 1
  function _zle_line_init() {
    # do whatever it is you actually wanted to do in zle-line-init here
  }
  _zle_line_init
}

Ie, to set local history by default when you start the shell, because
it has to be run from within a widget, but you may want to toggle it
while running the shell so it can't stay in the line-init hook.
Therefore, do it the first time, and then redefine the hook to do
something else.

-- 
Mikael Magnusson


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

* Re: wheels within wheels
  2015-09-30  3:40                                 ` Bart Schaefer
  2015-09-30  4:03                                   ` Mikael Magnusson
@ 2015-09-30  4:15                                   ` Ray Andrews
  2015-09-30  7:05                                     ` Bart Schaefer
  2015-09-30  8:01                                     ` ZyX
  1 sibling, 2 replies; 45+ messages in thread
From: Ray Andrews @ 2015-09-30  4:15 UTC (permalink / raw)
  To: zsh-users

On 09/29/2015 08:40 PM, Bart Schaefer wrote:
> }
> } I just learned that it's possible to declare a function within another
> } function.  A strange liberty.
>
> Interpreted language.

Yes.  It's so easy to forget that.
>      function foo {
>        echo defining bar
>        function bar {
> 	echo hello from bar
>        }
>        echo redefining foo
>        function foo {
> 	echo hello from new foo
> 	bar
>        }
>        # this looks like infinite recursion,
>        # but it is not, because foo was redefined
>        foo
>      }
>
>
Now that is mind expanding.  If you tried that in C you'd collapse the 
universe.
Interpreted .... sure, it can saw off the branch it's sitting on because 
there is no
tree.  Each command is past when it's past so that must mean that the 
address of
first foo ... is there ... yes of course there is, the thing is in 
memory ... just aborts
when second foo comes along.  It will expect grammatical completion of 
first foo
for the sake  of etiquette.  And when foo calls itself, it calls new foo 
which is
not recursive.  I am not yet able to snatch the pebble out of your hand, 
but that's
a zsh koan.


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

* Re: wheels within wheels
  2015-09-30  4:15                                   ` Ray Andrews
@ 2015-09-30  7:05                                     ` Bart Schaefer
  2015-09-30 15:06                                       ` Ray Andrews
  2015-09-30  8:01                                     ` ZyX
  1 sibling, 1 reply; 45+ messages in thread
From: Bart Schaefer @ 2015-09-30  7:05 UTC (permalink / raw)
  To: zsh-users

On Sep 29,  9:15pm, Ray Andrews wrote:
}
} Each command is past when it's past so that must mean that the address
} of first foo ... is there ... yes of course there is, the thing is in
} memory ... just aborts when second foo comes along.

No, the outer foo will happily keep executing until it returns, at
which point it is garbage-collected.  The old body has merely been
disconnected from the name.

    function foo {
      echo defining bar
      function bar {
	echo hello from bar
      }
      echo redefining foo
      function foo {
	echo hello from new foo
	bar
      }
      foo
      echo goodbye from the old foo
    }


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

* Re: wheels within wheels
  2015-09-30  4:15                                   ` Ray Andrews
  2015-09-30  7:05                                     ` Bart Schaefer
@ 2015-09-30  8:01                                     ` ZyX
  2015-09-30 15:18                                       ` Ray Andrews
  1 sibling, 1 reply; 45+ messages in thread
From: ZyX @ 2015-09-30  8:01 UTC (permalink / raw)
  To: Ray Andrews, zsh-users

30.09.2015, 07:16, "Ray Andrews" <rayandrews@eastlink.ca>:
> On 09/29/2015 08:40 PM, Bart Schaefer wrote:
>>  }
>>  } I just learned that it's possible to declare a function within another
>>  } function. A strange liberty.
>>
>>  Interpreted language.
>
> Yes. It's so easy to forget that.
>>       function foo {
>>         echo defining bar
>>         function bar {
>>          echo hello from bar
>>         }
>>         echo redefining foo
>>         function foo {
>>          echo hello from new foo
>>          bar
>>         }
>>         # this looks like infinite recursion,
>>         # but it is not, because foo was redefined
>>         foo
>>       }
>
> Now that is mind expanding. If you tried that in C you'd collapse the
> universe.
> Interpreted .... sure, it can saw off the branch it's sitting on because
> there is no
> tree. Each command is past when it's past so that must mean that the
> address of
> first foo ... is there ... yes of course there is, the thing is in
> memory ... just aborts
> when second foo comes along. It will expect grammatical completion of
> first foo
> for the sake of etiquette. And when foo calls itself, it calls new foo
> which is
> not recursive. I am not yet able to snatch the pebble out of your hand,
> but that's
> a zsh koan.

Nested *same* function definition is rather useful for initialization. Or when you need to alter the implementation based on some condition, and want to cache this to not check this condition again:

    # This will parse json array passed as argument to a shell array $reply.
    # Depending on whether zpython module is available it will either use built-in python interpreter support
    # which is faster or call python in a subshell.
    parse_json_array() {
        if zmodload libzpython 2>/dev/null ; then
            parse_json_array() {
                zpython 'import zsh, json; zsh.setvalue("reply", json.loads(zsh.getvalue("1")))'
            }
        else
            parse_json_array() {
                reply=( "${(@0)"$(python -c 'import sys, json; sys.stdout.write("\0".join(json.loads(sys.argv[1])))' "$1")"}" )
            }
        fi
        parse_json_array "$@"
    }

. Also this is a feature sometimes useful for metaprogramming: you can create a function which defines a function through eval. Will be needed if you for some reason want something like bash `export -f` feature.

And this is *not* a zsh koan. I have been using the same technique for the same reasons in Python: e.g. in https://github.com/ZyX-I/powerline/blob/5ebf0875b85f85e7cd4c1e07aa8cdebbcc3bd17e/powerline/segments/common/bat.py#L163. Many interpreted languages allow this. Specifically *all* POSIX-like shells I know allow this: https://github.com/ZyX-I/powerline/blob/5ebf0875b85f85e7cd4c1e07aa8cdebbcc3bd17e/powerline/bindings/shell/powerline.sh#L74-L99 is known to work in dash, [m]ksh, busybox ash and bash.

In C you may do something similar if you use function pointer as a public interface and store different address, but this makes call indirect. If you are OK with binding yourself to GCC you can even have nested definitions.


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

* Re: wheels within wheels
  2015-09-30  7:05                                     ` Bart Schaefer
@ 2015-09-30 15:06                                       ` Ray Andrews
  0 siblings, 0 replies; 45+ messages in thread
From: Ray Andrews @ 2015-09-30 15:06 UTC (permalink / raw)
  To: zsh-users

On 09/30/2015 12:05 AM, Bart Schaefer wrote:
> On Sep 29,  9:15pm, Ray Andrews wrote:
> }
> } Each command is past when it's past so that must mean that the address
> } of first foo ... is there ... yes of course there is, the thing is in
> } memory ... just aborts when second foo comes along.
>
> No, the outer foo will happily keep executing until it returns, at
> which point it is garbage-collected.  The old body has merely been
> disconnected from the name.
That's better.  It's not 'abandoned' it just becomes nameless.  Else 
we'd have
orphan lines of code and that's not sanitary.


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

* Re: wheels within wheels
  2015-09-30  8:01                                     ` ZyX
@ 2015-09-30 15:18                                       ` Ray Andrews
  0 siblings, 0 replies; 45+ messages in thread
From: Ray Andrews @ 2015-09-30 15:18 UTC (permalink / raw)
  To: zsh-users

On 09/30/2015 01:01 AM, ZyX wrote:
> Nested *same* function definition is rather useful for initialization. Or when you need to alter the implementation based on some condition, and want to cache this to not check this condition again:
Sure, I see that this sort of thing has it's power.  But this discussion 
has mostly involved redefining
a function within itself, not defining function A within function B so 
Kurtis' comments are still
cogent.  I'm looking at Sebastian's curses stuff and he does have nested 
definitions so I'm
curious as to the reason.

>    And this is *not* a zsh koan.

I just meant that Bart's example was a powerful and pointed 
demonstration of the right way of seeing
the issue.


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

end of thread, other threads:[~2015-09-30 15:48 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-17 15:54 autoload Ray Andrews
2015-09-17 17:34 ` autoload Bart Schaefer
2015-09-17 19:22   ` autoload Ray Andrews
2015-09-17 20:40     ` autoload Bart Schaefer
2015-09-17 23:06       ` autoload Ray Andrews
2015-09-17 23:20         ` autoload Bart Schaefer
2015-09-18  1:20           ` autoload Ray Andrews
2015-09-18  4:04             ` autoload Bart Schaefer
2015-09-18  5:00               ` autoload Ray Andrews
2015-09-18  5:52                 ` autoload Bart Schaefer
2015-09-18 15:49                   ` autoload Ray Andrews
2015-09-18 16:52                     ` autoload Bart Schaefer
2015-09-18 18:29                       ` autoload Ray Andrews
2015-09-18 19:02                         ` autoload Bart Schaefer
2015-09-18 22:57                           ` autoload Ray Andrews
2015-09-19  0:14   ` autoload Bart Schaefer
2015-09-19 15:04     ` autoload Ray Andrews
2015-09-19 16:29       ` autoload Bart Schaefer
2015-09-19 18:13         ` autoload Ray Andrews
2015-09-19 21:22           ` autoload Bart Schaefer
2015-09-19 22:12             ` autoload Ray Andrews
2015-09-20  5:53               ` autoload Bart Schaefer
2015-09-20 15:37                 ` autoload Ray Andrews
2015-09-20 15:59                   ` autoload Bart Schaefer
2015-09-20  0:58             ` autoload Ray Andrews
2015-09-20  5:41               ` autoload Bart Schaefer
2015-09-20 23:21                 ` autoload Ray Andrews
2015-09-21  4:18                   ` autoload Bart Schaefer
2015-09-21 17:03                     ` autoload Ray Andrews
2015-09-21 18:17                       ` autoload Bart Schaefer
2015-09-21 20:09                         ` autoload Ray Andrews
2015-09-22  3:19                           ` autoload Bart Schaefer
2015-09-22 17:33                             ` autoload Ray Andrews
2015-09-23  4:39                               ` autoload Bart Schaefer
2015-09-23 15:06                                 ` autoload Ray Andrews
2015-09-29 23:16                             ` wheels within wheels Ray Andrews
2015-09-30  2:55                               ` Kurtis Rader
2015-09-30  3:24                                 ` Ray Andrews
2015-09-30  3:40                                 ` Bart Schaefer
2015-09-30  4:03                                   ` Mikael Magnusson
2015-09-30  4:15                                   ` Ray Andrews
2015-09-30  7:05                                     ` Bart Schaefer
2015-09-30 15:06                                       ` Ray Andrews
2015-09-30  8:01                                     ` ZyX
2015-09-30 15:18                                       ` Ray Andrews

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).