Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Associative Arrays



On Thu, 21 Oct 2004, Nikolai Weibull wrote:

> * Stephane Chazelas <Stephane.Chazelas@xxxxxxxxx> [Oct 21, 2004 13:10]:
> > > I'm have a few questions regarding associative arrays.  What exactly 
> > > is the A flag for parameter expansion for?  I mean, how does one use 
> > > it, and how does one use the AA flag?
> >
> > : ${(AA)=a::=foo bar}
> 
> aha, OK.  How very useful.

Obviously one would be more likely to use it as ${(AA)=a:=foo bar} (note
only one colon) where it assigns only if the hash is empty.

> > > Is there any way to pass an associative array as ONE argument to a 
> > > function and easily deal with it as the same associative array in 
> > > the other function?

I note in passing that this is not just an issue with associative arrays. 
The shell language (not just zsh's language) in general lacks a way to 
truly pass by reference rather than by value.

> > > The easiest way seems to be the "pass-by-reference" technique, where 
> > > one simply passes the name of the array and then use the P flag to 
> > > deal with it.

That's one way.  Another way is simply to make use of dynamic scoping, so
that the called function treats the variable as global, and the calling
function restricts the scope when necessary.  Part of the function's API
then becomes the name of the variable that it expects to manipulate.

(This is one reason why ksh has "namerefs" so that you can explicitly 
alias two names to the same value, which is after all what happens 
implicitly in other languages when a call-by-reference parameter is 
passed.)

Or am I misreading the question?  Are you asking how to pass-by-value an
associative array?

> > You could use "${${(@qqkv)A}[*]}"
> >
> > So that in the function you can have
> >
> > typeset -A local_hash
> > local_hash=("${(Q@)${(z)1}}")
> 
> Aha, double quotation and then dequoting.  What a bitch...is this
> seriously the simplest/only ways to do it?

If you want to pass its entire value as a single positional parameter, 
that's pretty close to the only way.  However, you have the entire set
of positional parameters to play with.

Think like a Perl programmer, and imagine you're trying to pass a set of 
name-value pairs as @_.  You'd probably write something like

 sub blather {
   my $unnamed1 = shift;
   my $unnamed2 = shift;
   my %named = @_;
   if ($named{'winnie'} eq 'pooh') { print "Oh, stuff and bother\n"; }
 }

So in zsh that'd be

 function blather {
   local unnamed1=$1; shift
   local unnamed2=$2; shift
   local -A named; set -A named "$@"
   if [[ $named[winnie] = pooh ]]; then print "Oh, stuff and bother\n"; fi
 }

> I'd say that shell programming would be a lot simpler as a whole if this 
> was simpler.

Hey, it's only been a few years now that shells have had associative 
arrays AT ALL.  Imagine what shell programming was like in the old days.



Messages sorted by: Reverse Date, Date, Thread, Author