Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to reference outer-scope parameter? #14

Open
okdana opened this issue Jul 7, 2018 · 2 comments
Open

Ability to reference outer-scope parameter? #14

okdana opened this issue Jul 7, 2018 · 2 comments
Labels

Comments

@okdana
Copy link
Owner

okdana commented Jul 7, 2018

I have often wished for the ability to directly reference an outer-scope parameter (bypassing any local parameters of the same name). This would be most useful for supporting functions that take the name of a parameter to be acted upon. Consider the following:

# Assign a value to the named association
# $1 => the name of the association to assign to
mkassoc() {
  local -A a_
  a_=( foo 1 bar 2 ) # Pretend this is useful
  : ${(PAA)1::="${(@kv)a_}"}
}
# This works
local -A a;  mkassoc a
# This doesn't — it only modifies a_ in the local scope
local -A a_; mkassoc a_

What i'd like is some feature — whether an expansion flag or an option to typeset — that tells zsh to use the outer-scope version of the parameter.

I was able to get this working for parameter reads pretty easily (only like five lines of code changed), but parameter writes (as in the above example) are more difficult because those are performed by name only. Many parts of the code seem to have the expectation that they'll be able to access the correct parameter by name, in fact.

The only way i can think of to get around that (besides fucking with the whole API) is maybe like making a clone of the original parameter but with some special prefix to the name that can't be used by a real parameter (like outer/). But that feels shitty. idk.

In the mean time, there are only two feasible work-arounds that i know of:

  1. Prefix or suffix all of the function's local variables by a string of characters that's unlikely to be used in an outer scope. In order to allow two such functions to call each other, the strings would have to be pretty unique — maybe the first four characters of the base32 of the raw output from a hash of the function name. Even then, the function would still break if it called itself recursively.

  2. Use a function EXIT trap (in combination with some very careful quoting) to set the outer-scope parameter after the function has returned to the calling scope. The setting of the parameter itself should be quite reliable, but you would still have issues if you needed to do anything with the parameter from inside the function (like check to see if it's defined).

@okdana okdana added enhancement question unreported Not reported to the ML labels Jul 7, 2018
@okdana
Copy link
Owner Author

okdana commented Jul 7, 2018

pws apparently doesn't like this idea — not surprised tbh.

cf. workers/18792, workers/18794

@okdana
Copy link
Owner Author

okdana commented Dec 31, 2018

Oliver's almost-finished implementation of namerefs from workers/15058 would at least partially address this, since it retains the local level of the referenced parameter at the time of definition.

It's not a complete solution for me, though, since it can't work with special parameters like argv (which are set automatically when entering a new function scope), and even for normal parameters, you have to define the reference before any locals, which precludes it from working quite reliably in conjunction with argument parsing and similar.

It could be an inspiration though; at the very least it shows how to resolve outer-scope parameters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant