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

Re: syntax error with anonymous functions when an argument begins with (



On Sun, 31 Jul 2011 16:17:15 +0200
Jilles Tjoelker <jilles@xxxxxxxx> wrote:
> > [people want stuff like () { echo yay } (a|b)]
> 
> In fact, the closing brace may validly be followed by certain keywords
> in older zsh, for example
> 
>   if :; then () { echo hi; } else () { echo bye; } fi
> 
> prints "hi" in zsh 4.3.12 from FreeBSD ports.

You're quite right that this used to behave like if-then-else in 4.3.12
and now no longer does.

However, I don't think it's a problem that anonoymous functions work
differently from other functions: they're a new feature in recent
(theoretically unstable) versions of zsh and we can define them to work
however seems convenient.  If arguments are more useful than the
abbreviated syntax above, we can use them, suitably documented.  If
people really prefer the strict compatibility with other function
syntax, we are, as you say, stuck.  Personally, I think the function
syntax with keywords immediately following is screwy enough I don't feel
the need to follow it for anonymous functions.

But your point that we need to be careful with incompatibilities in
other cases is certainly a good one regardless of the above.  Luckily we
can see very early if the syntax is for an anonymous function, so I
think that's relatively straightforward, as follows (obviously, people
may see something I've missed).  (As we're looking for keywords, and "("
to start a subshell apparently isn't useful at this point, in fact I
hadn't broken anything I know to be correct --- but it's easy to be
safe.)

Index: Doc/Zsh/func.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/func.yo,v
retrieving revision 1.28
diff -p -u -r1.28 func.yo
--- Doc/Zsh/func.yo	19 Jun 2011 20:12:00 -0000	1.28
+++ Doc/Zsh/func.yo	31 Jul 2011 18:32:26 -0000
@@ -162,8 +162,15 @@ is not stored for future use.  The funct
 
 Arguments to the function may be specified as words following the
 closing brace defining the function, hence if there are none no
-arguments (other than tt($0)) are set.  Note that this means
-the argument list of any enclosing script or function is hidden.
+arguments (other than tt($0)) are set.  This is a difference from the
+way other functions are parsed: normal function definitions may be
+followed by certain keywords such as `tt(else)' or `tt(fi)', which will
+be treated as arguments to anonymous functions, so that a newline or
+semicolon is needed to force keyword interpretation.
+
+Note also that the argument list of any enclosing script or function is
+hidden (as would be the case for any other function called at this
+point).
 
 Redirections may be applied to the anonymous function in the same manner as
 to a current-shell structure enclosed in braces.  The main use of anonymous
Index: Src/parse.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/parse.c,v
retrieving revision 1.89
diff -p -u -r1.89 parse.c
--- Src/parse.c	28 Jul 2011 09:20:27 -0000	1.89
+++ Src/parse.c	31 Jul 2011 18:32:26 -0000
@@ -1465,7 +1465,10 @@ par_funcdef(void)
 	    ecssub = oecssub;
 	    YYERRORV(oecused);
 	}
-	incmdpos = 0;
+	if (num == 0) {
+	    /* Anonymous function, possibly with arguments */
+	    incmdpos = 0;
+	}
 	zshlex();
     } else if (unset(SHORTLOOPS)) {
 	lineno += oldlineno;
@@ -1721,7 +1724,10 @@ par_simple(int *complex, int nr)
 		    ecssub = oecssub;
 		    YYERROR(oecused);
 		}
-		incmdpos = 0;
+		if (argc == 0) {
+		    /* Anonymous function, possibly with arguments */
+		    incmdpos = 0;
+		}
 		zshlex();
 	    } else {
 		int ll, sl, c = 0;
Index: Test/C04funcdef.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/C04funcdef.ztst,v
retrieving revision 1.9
diff -p -u -r1.9 C04funcdef.ztst
--- Test/C04funcdef.ztst	28 Jul 2011 09:20:07 -0000	1.9
+++ Test/C04funcdef.ztst	31 Jul 2011 18:32:26 -0000
@@ -245,6 +245,12 @@
 >empty
 >here
 
+  if true; then f() { echo foo1; } else f() { echo bar1; } fi; f
+  if false; then f() { echo foo2; } else f() { echo bar2; } fi; f
+0:Compatibility with other shells when not anonymous functions
+>foo1
+>bar2
+
 %clean
 
  rm -f file.in file.out
-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



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