From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3354 invoked by alias); 31 Jul 2011 18:39:37 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 29633 Received: (qmail 20814 invoked from network); 31 Jul 2011 18:39:34 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 Received-SPF: neutral (ns1.primenet.com.au: 74.125.82.43 is neither permitted nor denied by SPF record at ntlworld.com) X-ProxyUser-IP: 86.27.188.118 Date: Sun, 31 Jul 2011 19:39:22 +0100 From: Peter Stephenson To: zsh-workers@zsh.org Subject: Re: syntax error with anonymous functions when an argument begins with ( Message-ID: <20110731193922.237278da@pws-pc.ntlworld.com> In-Reply-To: <20110731141715.GA66652@stack.nl> References: <20110731141715.GA66652@stack.nl> X-Mailer: Claws Mail 3.7.9 (GTK+ 2.24.4; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Sun, 31 Jul 2011 16:17:15 +0200 Jilles Tjoelker 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 Web page now at http://homepage.ntlworld.com/p.w.stephenson/