bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Passing variables by reference conflicts with local


From: Greg Wooledge
Subject: Re: Passing variables by reference conflicts with local
Date: Thu, 26 Apr 2012 08:28:16 -0400
User-agent: Mutt/1.4.2.3i

On Mon, Apr 23, 2012 at 04:56:09PM +0800, Clark Wang wrote:
> When I revisit this 2 years old thread I don't understand why following
> foo() function does not output the global var:
> 
> $ cat foo.sh
> var=global
> foo()
> {
>     local var=foo
>     unset var
>     echo foo: $var
> }
> bar_unset()
> {
>     unset var
> }
> bar()
> {
>     local var=bar
>     bar_unset
>     echo bar: $var
> }
> foo
> bar
> $ bash foo.sh
> foo:
> bar: global
> $
> 
> In foo() it unsets its local var so why doesn't the subsequent $var refer
> to the global var?

Well, the manual certainly doesn't give enough information to figure it
out.

      unset [-fv] [name ...]
           For each name, remove the corresponding variable or function.  If
           no options are supplied, or the -v option is given, each name
           refers to a shell variable.  Read-only variables may not be
           unset.  If -f is specified, each name refers to a shell function,
           and the function definition is removed.  Each unset variable or
           function is removed from the environment passed to subsequent
           commands.  If any of COMP_WORDBREAKS, RANDOM, SECONDS, LINENO,
           HISTCMD, FUNCNAME, GROUPS, or DIRSTACK are unset, they lose their
           special properties, even if they are subsequently reset.  The
           exit status is true unless a name is readonly.

Apparently there's a lot more going on than just "remove the corresponding
variable or function".

http://fvue.nl/wiki/Bash:_Unset says that unset will "traverse down the
call-stack and unset variables repeatedly", which is fine, but that
still doesn't explain what you're asking.

So, here's my guess: when you unset a local variable within the same
function where the variable was defined, bash assumes you explicitly
want the variable to remain unset within that function.  In foo(),
you make a local var and then unset var.  Bash believes you expect $var
to be empty for that function.

However, when you unset a variable from a different function where it's
*not* locally defined, then unset traverses back through the dynamic
scope stack of definitions for that variable, and whacks the topmost one.
Thus, in bar_unset(), you call unset var, but there's no local copy of
var, so it looks back through the stack, finds one in bar(), and gets
rid of that one.  Then the only remaining definition of var is the global
one.  So when you return to bar(), only the global one remains.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]