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

Re: 4.3.17 unset RPS1 vs RPROMPT



On Jun 29, 10:05pm, Phil Pennock wrote:
}
} If the name could be rebound to another variable and no longer be magic,
} the current approach would be sane, but it seems that perhaps the
} correct behaviour should be to ensure that whatever the state of one
} name, the other name should be in the same state: set, unset, empty,
} with-content, whatever.

There's some precedent for this; although $#, $@ and $* are read-only
variables, if you "unset argv" you erase $* and $@, and $# becomes 0.
On the other hand, argv has its own weird semantics (see below) which
probably exempts it from this analogy.

} Perhaps I've become contaminated with the Pythonic approach of being
} distinct about the binding of a name to a variable versus the changing
} of the value of a variable.

I think this comes down to a scoping issue.

Shell variables have a form of dynamic scoping that's somewhat different
from that of any other interpreted language.  In the first shells, all
variables were environment variables.  Then shell variables became a
separate thing and the idea of exporting them into the environment was
introduced, but there was still only one global scope.  Then local scopes
were introduced, but to retain the semantics of the former global scope,
the local scopes became dynamic, based on runtime call heirarchy rather
than code structure.

Once a shell variable has a scope, unsetting the variable does not delete
it from that scope.  If you re-use the name, it returns in the same scope
where it was originally defined, unless you are declaring it in a new
dynamic scope.  You can't change the magic binding in the original scope;
that's what it means for the variable to be "special".

But you can rebind them in any scope other than the global one, and thus
in all dynamically nested scopes, with e.g. "local -h RPROMPT".

Weird semantics:  Although argv is seems implicitly to be local in all
scopes, unsetting without first actually declaring it local causes it
to disappear in all scopes, which breaks the connection to $* et al.

torch% showargv() { print -l "argv: $argv" "*: $*" }
torch% noargv() { print -l "argv: $argv"; unset argv; print "*: $*" }
torch% showargv one two three
argv: one two three
*: one two three
torch% noargv four five six
argv: four five six
*: 
torch% showargv seven eight nine
argv: 
*: seven eight nine
torch% noargv gone gone gone
argv: 
*: gone gone gone
torch% 

Resetting it brings it back with full magic intact:

torch% argv=()
torch% showargv seven eight nine
argv: seven eight nine
*: seven eight nine
torch% 

Of course I say "seems" to be local in all scopes because really it's
the special binding to $@ and $* that makes it local; the name itself
and its properties are still defined in the global scope.



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