On Thu, May 5, 2016 at 2:46 AM, Piotr Grzybowski <narsil...@gmail.com> wrote: > ok, so Dan wants this patch.
Yes I think your bash patch is probably an improvement at least in this particular case. > Maybe you can comment on wether the patches are valid. The posix export and readonly don't produce locally scoped variables at all, so it's expected that e.g. `typeset -x` and `export` will differ. This is yet another problem that's better solved by immutable C++-like references. At least, the problem goes away when variables are passed explicitly. The exact mechanism isn't really documented. When ksh determines that a nameref assignment is to a positional parameter during evaluation, you get a completely different type of reference. That is, if `$1` expands to `x`, then `typeset -n ref=$1` and `typeset -n ref=x` aren't equivalent like they are in bash. In the former case, any use of `ref` except for `typeset +n` and `unset -n` applies to the exact object that `$1` referred to at the time the reference was created, even if it's another nameref in which case that reference is followed. The latter gives you a bash-like dynamic reference that points to somewhere within either the current scope or the global scope (due to static scoping) unless it happens to point to another reference parameter of course. When you changed that `typeset` line to `export -r _x`, things become less clear. Ksh sees that _x is a reference parameter and because of the rules it does the only thing that makes sense which is apply the export attribute to whatever was passed to the function for both `export` or `typeset -x`, though there may be some other differences between those. Bash on the other hand never does what you'd want for either `export` or `typeset -x`. For typeset, it tears down the reference and redefines it as a new local with the export attribute. It does that indiscriminately for any usage of typeset, which means you can't correctly modify an attribute by reference in bash. If you actually wanted that result, the correct way would be to first use `typeset +n _x` followed by `typeset -x _x`. If you choose `export`, the correct behavior is even less clear thanks to dynamic scope. Your patch is a partial solution that makes `export` modify the attribute in the way you would expect in the absence of the reference parameter feature. Ignoring namerefs, the only other way for bash to modify the attribute of the currently visible dynamically scoped local without declaring a new local is to use export, which is why bash behaves as it did. This solution doesn't solve the same problem for attributes other than export and readonly. Bash can't use e.g. `typeset -u` by reference. It also doesn't solve the many other problems caused by this like name conflicts.