bug-bash
[Top][All Lists]
Advanced

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

Re: Unset array doesn't work


From: Robert Elz
Subject: Re: Unset array doesn't work
Date: Thu, 01 Mar 2018 02:00:00 +0700

    Date:        Wed, 28 Feb 2018 10:27:23 -0500
    From:        Chet Ramey <chet.ramey@case.edu>
    Message-ID:  <ba594d01-b9c4-5cd8-9fa0-2f20fd1d2d07@case.edu>

  | These are two different cases -- same context vs. a previous context. Your
  | example is not the same as the original poster's.

OK, though I am not sure why that should make a difference.

  | This was poorly phrased, but I amended it in a subsequent message.

Yes, I saw the update - I only quoted that part to make the point that I had 
not seen (or if I did, it was briefly, and I no longer recall it) the original 
message. 
The original problem isn't, or wasn't (still isn't) material to my comment.
Quoting from multiple messages is more work, and this was not important,
so I just kept the original.

  | The global var is left unchanged, and satisfies references to $var with v1.

The second clause of that is what is brain dead.   There should be a simple
invariant in all shell contexts, which is

        unset X
        Y=$X

assigns the null string to Y (except in the case where X is read only, which
is not a case of concern here.)

Always.

No (other) exceptions.

None.

Similarly the expression ${X-unset} should always produce "unset" if X
has been unset and not subsequently given a value.

Whatever else is believed about how variables should work, that part should
remain true - if we cannot rely upon unset working to create an unset variable,
then we're lost.

I could almost understand it in the context of the unset being in the same
function as the variable was declared local - that is, defining unset to be
some kind of unlocal command (though I think it would be a very poor idea
to abuse unset that way - if an unlocal is needed, make it something different)
but having that happen, in a function that believes that X is just some global
variable name is lunacy (where it happens not to be as it was called
from another function which had made X local.)

  | The original poster wanted ...

No comment on that, he/she can speak for him/herself if there's anything 
here relevant to the original message.

It sounds from what you are saying that the request was for static scoped
variables (what David Korn wanted to have, as I understand it) - the same
kind of vars that exist in most compiled programming languages.   if so,
I agree, that is not what the shell offers (except perhaps ksh when using its 
"function x" type functions.)   Dynamic scoping is far more useful in
languages like sh (particularly ones used interactively.)

  | There is code that implements your preferred interpretation of `removed'
  | when the `unset' is performed in the same context as the local variable
  | declaration. When `unset' removes a variable at a previous scope, which
  | can be a calling function due to dynamic scoping, it just removes the
  | variable.

If there was a justification for different cases, that's backwards.   But 
better to always simply make unset do an unset on whatever the currently
visible instance of the variable is, and leave it at that.

  | There are several behavior choices here. You can simply remove all
  | instances of the variable back to the global scope until there are no
  | traces of the name remaining. 

That would be wrong.   The whole point of "local" is so that functions can
use variable names without caring whether the same name exists in the
caller's scope - changing anything other than the local copy would defeat
that purpose.

  | You can mark any local instances in previous
  | scopes (or the nearest previous scope that has a local instance of
  | that variable) with a special `unset' attribute that will cause
  | references to it to behave as if it were unset, leaving the global
  | value unchanged. 

Yes.   That's the correct way I believe.   One way to implement that
is simply to unset (however that is implemented in the case of global
vars and no functions at all) the variable - and then when the function
that made the variable local returns, replace the previous value/attributes
from somewhere they had been saved.   Or there can be some ":var is
unset" flag.   Or probably several other implementation choices.

  | Or you can remove the instance in the nearest previous
  | scope in the call chain, leaving other instances alone. Bash chooses
  | the last.

Apparently except when the nearest previous scope is the current scope?

I can only imagine that the reason for this is that any other behaviour would
generate complaints by the millions - and that there are less in the other
cases is merely because it is rare for this to ever actually happen.

Are you sure that the original complaint was not just that after "unset X"
X was not null (in the scope where the unset was performed) ?

Lastly, where does the notion of "remove" come from?   unset is unset.
There's nothing in POSIX about removing anything, just unsetting the
variable (and no longer exporting it).  As an implementation technique
you might (and probably would) choose to remove the data structs related
to a variable that has been unset, just to save memory, but that's purely
implementtaion, and should not affect the visible behaviour.  If you believe
some kind of variable removing command is needed, implement that - just
don't call iit unset.

kre




reply via email to

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