zsh-users
 help / color / mirror / code / Atom feed
* Uses of "anonymous functions"
@ 2011-05-26  3:29 Bart Schaefer
  2011-05-26  3:55 ` Bart Schaefer
  0 siblings, 1 reply; 2+ messages in thread
From: Bart Schaefer @ 2011-05-26  3:29 UTC (permalink / raw)
  To: zsh-users

A few releases ago, zsh introduced what it calls "anonymous functions".
These aren't closures in the sense of anonymous functions in a number
of other languages; rather, they're nameless function scopes that are
executed as soon as they are defined.  It's a lot like writing in Perl:

    &{sub { print "this happens immediately!\n" }};

The most interesting uses of these nameless scopes are to control the
extents of option settings and of local variables.

For example, one issue in zsh has always been how to write a generic [*]
shell function that sets an option in the caller's scope.  If you start
such a function with "emulate zsh", then you set too many options in
the calling scope.  If instead you start with "emulate -L zsh" then
you are prevented from setting any options in calling scope.  With a
nameless scope, you can apply emulation and other options exactly where
you need them:

    if (){ emulate -LR zsh; setopt extendedglob;
           [[ $1 = (#b)no([:IDENT:]##) ]] }
    then unsetopt ${match[1]}
    fi

(This doesn't create a function named "if" because "if" is a keyword.)

As another example, suppose you want to read a script file written for
a POSIX shell, but which you know references a variable such as $argv
that has special meaning to zsh.  You don't want to unset argv in the
current scope, because that will have the side-effect of deleting the
values of $* and $@.  Nameless scope to the rescue:

    (){ local argv; unset argv; emulate sh -c '. posix_script' }

Like any shell function, the nameless scope will have the same return
status as the last command it executes, so $? will have the same value
as if ". posix_script" had been executed directly.  The problem does
remain, though, that any "typeset" commands in the posix_script will
create locals in the nameless scope, so keep that in mind.

As a final example, consider the "trap" command.  Signal handlers
defined with "trap" have a number of properties that differ from those
defined by a TRAP* function, most importantly the treatment of their
return status and that "trap" handlers are reset within subshells.  On
the other hand, "trap" handlers execute in the context of their caller.
If you want the former behaviors but not the latter:

    trap '(){ print -l $zsh_eval_context }' ALRM

You can set TMOUT=5 in an interactive shell to see this in action.
Compare to each of:

    TRAPALRM() { print -l $zsh_eval_context }
    trap 'print -l $zsh_eval_context' ALRM

What other good uses of "anonymous functions" have you thought of?


[*] I would say "portable" but what I mean is a function that works in
zsh no matter what setopts the caller has used, not a function that works
in a variety of POSIX-like shells.


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

* Re: Uses of "anonymous functions"
  2011-05-26  3:29 Uses of "anonymous functions" Bart Schaefer
@ 2011-05-26  3:55 ` Bart Schaefer
  0 siblings, 0 replies; 2+ messages in thread
From: Bart Schaefer @ 2011-05-26  3:55 UTC (permalink / raw)
  To: zsh-users

On May 25,  8:29pm, Bart Schaefer wrote:
}
}     if (){ emulate -LR zsh; setopt extendedglob;
}            [[ $1 = (#b)no([:IDENT:]##) ]] }
}     then unsetopt ${match[1]}
}     fi

Oops, actualy that doesn't work exactly as written, because there is
no $1 in the nameless scope.  I over-simplified a working example.
A local is needed to pass $1 into the anonymous function, and I typo'd
the IDENT class:

    local arg="$1"
    if (){ emulate -LR zsh; setopt extendedglob;
           [[ $arg = (#b)no([[:IDENT:]]##) ]] }
    then unsetopt ${match[1]}
    fi

Sorry about that.


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

end of thread, other threads:[~2011-05-26  3:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-26  3:29 Uses of "anonymous functions" Bart Schaefer
2011-05-26  3:55 ` Bart Schaefer

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