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

Re: associative arrays: k flag in subscripts



On Thu, 31 Jul 2008 15:24:52 +0200
Julius Plenz <julius@xxxxxxxxx> wrote:
> Consider this example (executed in a zsh without any configuration
> done):
> 
>     zsh> local -A a
>     zsh> a=('[0-9]' digit '[0-9a-z]' alnum)
>     zsh> print $a[(k)3]
>     digit alnum
>     zsh> print $a[(K)3]
>     digit alnum
> 
> Actually, I expected the output "digit alnum" when I specified the K
> flag. But the k flag should behave differently, according to the
> manual: ``... and returns the value for the first key found where
> exp is matched by the key.''
> 
> So the expression $a[(k)3] should expand to either "digit" or "alnum",
> not to both -- right?

Right, though the ordering isn't specified (which the manual should
probably say in this specific case).  Because of the indeterminacy this
form isn't used very often.  I think it's simply a boolean the wrong way
round; this doesn't seem to break anything.  I've added a test.

Index: Doc/Zsh/params.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/params.yo,v
retrieving revision 1.47
diff -u -r1.47 params.yo
--- Doc/Zsh/params.yo	9 Apr 2008 13:06:55 -0000	1.47
+++ Doc/Zsh/params.yo	31 Jul 2008 13:42:11 -0000
@@ -263,9 +263,10 @@
 item(tt(k))(
 If used in a subscript on an associative array, this flag causes the keys
 to be interpreted as patterns, and returns the value for the first key
-found where var(exp) is matched by the key.  This flag does not work on
-the left side of an assignment to an associative array element.  If used
-on another type of parameter, this behaves like `tt(r)'.
+found where var(exp) is matched by the key.  Note this could be any
+such key as no ordering of associative arrays is defined.
+This flag does not work on the left side of an assignment to an associative
+array element.  If used on another type of parameter, this behaves like `tt(r)'.
 )
 item(tt(K))(
 On an associative array this is like `tt(k)' but returns all values where
Index: Src/params.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/params.c,v
retrieving revision 1.143
diff -u -r1.143 params.c
--- Src/params.c	25 Mar 2008 17:47:11 -0000	1.143
+++ Src/params.c	31 Jul 2008 13:42:12 -0000
@@ -1127,7 +1127,11 @@
 		v->isarr &= ~SCANPM_WANTVALS;
 	    } else if (rev)
 		v->isarr |= SCANPM_WANTVALS;
-	    if (!down && !keymatch && ishash)
+	    /*
+	     * This catches the case where we are using "k" (rather
+	     * than "K") on a hash.
+	     */
+	    if (!down && keymatch && ishash)
 		v->isarr &= ~SCANPM_MATCHMANY;
 	}
 	*inv = ind;
Index: Test/D06subscript.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/D06subscript.ztst,v
retrieving revision 1.12
diff -u -r1.12 D06subscript.ztst
--- Test/D06subscript.ztst	18 Mar 2008 15:14:23 -0000	1.12
+++ Test/D06subscript.ztst	31 Jul 2008 13:42:12 -0000
@@ -145,6 +145,16 @@
 >\2 backcbrack cbrack star
 >\\\4 \\\? star zounds
 
+# It doesn't matter which element we get, since we never guarantee
+# ordering of an associative array.  So just test the number of matches.
+  array=(${(o)A[(k)\]]})
+  print ${#array}
+  array=(${(o)A[(k)\\\]]})
+  print ${#array}
+0:Associative array keys interpreted as patterns, single match
+>1
+>1
+
   typeset -g "A[one\"two\"three\"quotes]"=QQQ
   typeset -g 'A[one\"two\"three\"quotes]'=qqq
   print -R "$A[one\"two\"three\"quotes]"



-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



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