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

Re: values of associations pointed by P flag



Bart Schaefer wrote:
> (And the doc could be
> clearer, but it all stems from the fact that zsh parameter expansion
> works by passing values of parameters, not references to parameters.)

[Moved to zsh-workers in order to ramble aimlessly.]

We really need passing by reference, though, not just for confusing cases
like this (I don't think I'd have guessed that you could use "hash[key]"
as an indirect reference, either), but for plenty of other uses.

One place I get into trouble all the time is passing back values, where
I'm always falling over the namespace problem:

  sub() {
    local foo

    foo=something_i_needed_to_work_out

    if [[ $1 = foo ]]; then
      print "Oops, I've got my own foo." >&2
      return 1
    else
      foo[thiskey]=some_expression_that_needs_passing_back_involving_$foo
      foo[thatkey]=another_one
    fi
  }

  fn() {
    local -A foo

    sub foo

    do_something_with ${(kv)foo}
  }

This sort of thing is the bread and butter of programming languages, yet
zsh has no good way of coping.  Something hacked up with "reply" as an
associative array is the best I can think of at the moment.

What I'd *really* like to be able to do is this:

  sub() {
      local foo

      <treat_as_opaque_ref($1)>=what_I_want_to_set
  }

  fn() {
    local foo

    sub <generate_opaque_reference_to_my(foo)>
  }

In other words, there would be something to generate an opaque reference
(a hard, rather than a symbolic) link to foo as found in fn(), and then
another mechanism for using that reference somewhere else.  fn and sub
would need to collaborate to use this, but if you can test for
parameters containing opaque references you can add backward compatible
code.  In fact, it could be as simple as using a hash code in a form
that can't be a parameter name:

% print <generate_opaque_reference_to_my(foo)>
#4351267a

The opaque reference could be exactly that string, as long as we've got
a way of turning it back internally a struct pm which isn't necessarily
the current entry in the parameter table for whatever the parameter is
named.  This could be made safe, for example this could be a pointer
with a parameter name; we would search through all parameters of that
name, and extract one with the address given by that pointer:

% foo=bar
% ref=<generate_opaque_reference_to_my(foo)>
% print $ref
#4351267a:foo
% print $<treat_as_opaque_ref($ref)>
bar
... [foo goes out of scope] ...
% print $<treat_as_opaque_ref($ref)>
zsh: reference to variable "foo" no longer in scope

This isn't *completely* safe, in that you could get a chance match with
a pointer to a later instance of foo; but that isn't catastrophic and
it's you're own fault for allowing it to go out of scope.  The check at
least it ensures it won't crash the shell.

However, that requires a complete list of all currently defined
variables even if they're not currently in scope, and unfortunately in
some cases we remove them temporarily from the parameter table.
Ordinary local variables are relatively straightforward since they're on
a linked list tied to the same entry in the parameter table.  If we can
resolve this problem there might be some mileage in the idea.

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php



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