zsh-users
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh Users <zsh-users@zsh.org>
Subject: Re: Local inner functions
Date: Wed, 23 Mar 2011 18:41:46 -0700	[thread overview]
Message-ID: <AANLkTinognOPQLV6xYNwuqJPJ=bHKs+AOM=suvz7MFY3@mail.gmail.com> (raw)
In-Reply-To: <4D8A810A.3050300@necoro.eu>

On Wed, Mar 23, 2011 at 4:23 PM, René 'Necoro' Neumann <lists@necoro.eu> wrote:
>
> foo ()
> {
>   bar () { }
> }
>
> Is there some way of making 'bar' to be local to 'foo'? Using the
> 'local' keyword does not work :).

The short answer is "no."  And you can't make local aliases either.

The slightly longer answer is that there are a couple of ways to fudge
it, of varying degrees of hackishness.

The first and least hackish is to use an "anonymous" function (which,
it has been pointed out elsewhere, are slightly misnamed because
they're not true closures):

foo() {
  local x=foo
  () {
    local x=bar
    print "Look, it's a nested scope: $x"
  }
  print "Back in the function scope: $x"
}

However, this only works when the inner scope needs to be called in
only one place, that is, you don't need to refer to it by name or pass
it arguments.  It's called immediately as soon as it's defined.

Alternately, as you mentioned, you can define your functions and then
unfunction them again.  If you employ an "always" block there
shouldn't be any situation where this doesn't work, but it does mean
you have to avoid name clashes.  The following assumes you setopt
FUNCTION_ARG_ZERO:

foo() {
  { # Begin "always" block
    function $0_bar {
      print "A function scope with a fudged name: $0"
    }
    print "Calling..."
    $0_bar
    print "... back in $0"
  } always {
    unfunction -m "$0_*"
  }
}

Now we reach the real hack.  If you don't care what your function is
named, you can hijack signal trapping functions for signals that it's
very unlikely your script will receive.  Examples are USR1, USR2, URG,
PWR, and SYS, but not all platforms have all those signals so in
practice you probably get only USR1 and USR2.

foo() {
  setopt localoptions localtraps
  TRAPUSR1() {
    print "A handler for a signal that never comes"
  }
  print "Calling..."
  TRAPUSR1
  print "... back in function scope"
}

The localtraps option causes the TRAPUSR1 function to be removed
automatically when the function scope ends.  It also does the right
thing if another function defines the same nested function name and
one of the two outer functions calls the other one.

(So theoretically the plumbing is all there to create local nested
functions, but the devil is in the details, as they say.)


  parent reply	other threads:[~2011-03-24  2:05 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-23 23:23 René 'Necoro' Neumann
2011-03-24  1:16 ` nix
2011-03-24  8:50   ` René 'Necoro' Neumann
2011-03-24  1:41 ` Bart Schaefer [this message]
2011-03-24  9:38   ` René 'Necoro' Neumann
2011-03-24 11:51     ` Mikael Magnusson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='AANLkTinognOPQLV6xYNwuqJPJ=bHKs+AOM=suvz7MFY3@mail.gmail.com' \
    --to=schaefer@brasslantern.com \
    --cc=zsh-users@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).