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

Re: typeset -p output gives shows variables which can't be read back in



Thanks for the information. The only thing I still don't understand or
disagree with is the "doomed from the start comment".

ksh introduced lexical scope for "function" kinds of functions, but I've not
seen lexical scope in zsh. It uses dynamic scoping; dynamic scope was
especially used in earlier versions of Lisp and was (is) the default for
Perl. ("my" was later added in Perl.)

In this kind of scope, it's sufficient to set the variable somewhere down
the call chain such as in the trace hook and that persists back to outside
the trace hook. I've tested this already in my nested shell example and it
works as expected. But of course here you have to be careful not to run some
sort of command that *defines* the variable again before the assignment or
else that will now be the point of a new scope for the variable's value.

So although on entry to the nested shell a definition of the type is either
necessary or useful, when writing a file on exit for later source'ing it is
not and is harmful: at the point in the debug hook where the values are
source'd back in to pick up changed values, an associative array's value has
already been defined scope-wise.

If one defines a *new* variable, that is, one that was not previously
defined before in the code being debugged, yes, there is no way to set that
down the call chain and have that picked up above where it might be intended
to be used.

But in the function which saves the variables I can probably check against
the original set of variables and give a warning (if this is an associative
array) that this kind of save is futile.


On Tue, Mar 1, 2011 at 12:59 AM, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>wrote:

> On Feb 28, 10:09pm, Rocky Bernstein wrote:
> }
> } Comments in line. In sum, thanks again for the code suggestion.  A
> } modified version of that I now use in the debugger.
>
> You're welcome; glad to help.
>
> } On Mon, Feb 28, 2011 at 2:09 AM, Bart Schaefer <
> schaefer@xxxxxxxxxxxxxxxx>wrote:
> }
> } > E.g. if I have
> } >
> } >    typeset -T SCALAR=x:y:z array
> } >
> } > and then I do
> } >
> } >    typeset -p SCALAR
> } >    typeset -p array
> } >
> } > should I get the exact same output both times?
> }
> } I don't understand the complexity let alone the ramifications here. If
> } you think it worthwhile or if others may be as confused as I am please
> } elaborate. (But I am probably not qualified to judge.)
>
> Well ... internally ...
>
> After "typeset -T SCALAR array" both SCALAR and array have the PM_TIED
> flag set, and each of them records the name of the other one in the
> ename field of the Param struct.  So theoretically when one asks for
> the typeset form of either of them, there's enough information to
> emit the correct typeset -T expression.  However, it's really only
> the scalar that stores the assignable value and the optional join
> character, so it takes an extra dereference to get from the name of
> the array to the Param for the scalar that has all the data.
>
> Upon "typeset -p array", then, the question is whether to discover
> the PM_TIED flag, and therefore look up the name of SCALAR and act as
> if "typeset -p SCALAR" had been invoked instead; or to just punt and
> output an assignment for the array as if it were not tied.
>
> When executing "typeset -p" with no other arguments the PM_TIED flag
> could be ignored for arrays because the corresponding typeset for the
> scalar is also going to be output.  That would make the entire dump
> self-consistent for reloading, but would make the output for the
> array incomplete if taken in isolation.  Which is the better course?
>
> You, I presume, would argue for the reloadable dump rather than for
> two assignments that are correct each alone but break when processed
> together.
>
> } In my simple-minded way of thinking, if I had previously issued:
> }    typeset -T SCALAR=x:y:z array
> }
> } then "typeset -p" I would imagine would print:
> }    typeset -T SCALAR=x:y:z array
>
> Hmm, perhaps it should output
>
>    typeset -T SCALAR=x:y:z array :
>
> to make the join character explicit.  Should the default be special-
> cased, or not?
>
> } what "typeset -p array" prints is another issue and dependent on the
> } definition of "array".
>
> It has to output one of two things.  Either
>
>    typeset -a array
>    array=(x y z)
>
> Or
>
>    typeset -T SCALAR=x:y:z array :
>
> } > Until you mentioned the debugger, I was completely at a loss to come up
> } > with an environment where you'd want to attempt to reload any parameter
> } > that is normally maintained by the shell internals (such as any of the
> } > variables in the $parameter module, or most of the other modules for
> } > that matter).  I still can't think of one.
> }
> } Alas again I am not sure I understand you here.
>
> I'm drawing a distinction between parameters to which the programmer
> has assigned values, and parameters for which the shell has in some
> automated or default fashion populated the values.  I can understand
> wanting to save and restore the former; the circumstances for the latter
> are harder to invent (and most of those variables are readonly besides,
> but not all).
>
> } Something I think likely is that I am inside a zsh session I've been
> } playing around writing definitions and trying tests and setting
> } variables and want to save out the environment so that sometime later
> } I can come back into zsh and set things up roughly as they were
> } before.
> }
> } Or perhaps in order to send back a bug report I want someone else
> } to be able to see the relations of things. They might have to edit
> } parts of that environment, but still the bulk of the settings would be
> } relevant.
>
> In both of those cases, though, there's a lot more that you need to
> save/restore than just parameters.  There's a whole (lengthy) script
> Util/reporter in the zsh distribution just for bug report purposes.
> (It's been around a long time and probably needs updating.)
>
> } >    for param in "${save_vars[@]}"
> } >    do case $parameters[$param] in
> } >       (*assoc*)
> } >         print -- "typeset -A $param; $param=( ${(P@kvqq)param} )";;
> } >       (*array*)
> } >         print -- "typeset -a $param; $param=( ${(P@qq)param} )";;
> } >       # etc.
> } >    done > $the_save_file
> } >
> } > The point being that one doesn't need to dump the entire output of
> } > typeset, only the parameters whose names are explicitly known.
> }
> } I hope you don't take offense, but the code you have above is a little
> } bit wrong.  We don't want to issue typeset commands because that will
> } cause the *scope* to change.
>
> No, no offense.  Unfortunately there's no way re-create an associative
> array without issuing a "typeset -A" command first.  If scope is going
> to be a problem, you need to figure out somehow whether what's needed
> is to use "typeset -gA ...".  That might be a good argument for turning
> this into C code, where you have access to the scoping level, etc.
>
> } In a debugger, one is in trap function which then invoked the nested
> } shell. The restore is done in the trap hook -- specifically in the
> } debugger's "shell" command. But the original definition of the
> } variable (if there is one) that a programmer typically wants to change
> } will not be in the hook, but farther away the call chain in the
> } debugged program.
>
> Indeed, that's what I was talking about when I alluded to being "doomed
> from the start" a couple of messages back in the thread ...
>


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