Re: Unsetting local variables

2017-03-17 Thread Thorsten Glaser
Martijn Dekker dixit:

>One nitpick with the new man page phrasing though:
>
>| Create parameters in global scope, not in local scope.
>
>That's not quite accurate, as was also explained by the old explanation

I think it entirely accurate and the old text too… clumsy.

The new text is really short, but I also changed the corresponding
text in the typeset description.

The “create in the global scope” vs. “create in the local scope”
is really what ±g is about. If the parameter already exists…

>scope." IOW, it may still inherit the enveloping local scope from a
>calling function.

… then it’s not created.

Hm. But then, maybe…

| Do not create parameters in function-local scope.

… would be even better? Because I now realise you _are_ right
in that they aren’t created in the global scope even with -g…
they are in fact not created at all if they already exist on
any scope (maybe _that_ must go into the text?).

So:

| If name arguments are given, the attributes of the named parame-
| ters are set (-) or cleared (+); inside a function, this will
| cause the parameters to be created (with no value) in the local
| scope. Values for parameters may optionally be specified.
| For name[*], the change in attributes affects all elements of
| the array, and no value may be specified.

And:

| -g  Do not cause named parameters to be created in
| the local scope when called inside a function.

Something like that, then?

Thanks,
//mirabilos, highly valuating your input (but kinda tired)
-- 
08:05⎜ mika: Does grml have an tool to read Apple
 ⎜System Log (asl) files? :)
08:08⎜ yeah. /bin/rm. ;)   08:09⎜ hexdump -C
08:31⎜ ft, mrud: *g*


Re: Unsetting local variables

2017-03-17 Thread Martijn Dekker
Op 17-03-17 om 23:08 schreef Thorsten Glaser:
> Martijn Dekker dixit:
> 
>> Op 17-03-17 om 20:53 schreef Thorsten Glaser:
>>> Even mksh’s “global” builtin does not access the global scope.
>>> It’s simply a “typeset” that’s not also “local”.
>>
>> But why the separate builtin (which is unique to mksh, if I'm not
>> mistaken) rather than 'typeset -g' as in zsh, bash 4 and yash?
> 
> Oh. I was not aware of that.
> 
> I think that’s sufficient to deprecate “global” even. Thanks!

Neat. :)

One nitpick with the new man page phrasing though:

| Create parameters in global scope, not in local scope.

That's not quite accurate, as was also explained by the old explanation
for the 'global' command which was patched out: typeset -g "does not
allow a function called from another function to access a parameter at
truly global scope, but only prevents putting an accessed one into local
scope." IOW, it may still inherit the enveloping local scope from a
calling function.

- M.



Re: Unsetting local variables

2017-03-17 Thread Thorsten Glaser
Martijn Dekker dixit:

>Op 17-03-17 om 20:53 schreef Thorsten Glaser:
>> Even mksh’s “global” builtin does not access the global scope.
>> It’s simply a “typeset” that’s not also “local”.
>
>But why the separate builtin (which is unique to mksh, if I'm not
>mistaken) rather than 'typeset -g' as in zsh, bash 4 and yash?

Oh. I was not aware of that.

I think that’s sufficient to deprecate “global” even. Thanks!

bye,
//mirabilos
-- 
>> Why don't you use JavaScript? I also don't like enabling JavaScript in
> Because I use lynx as browser.
+1
-- Octavio Alvarez, me and ⡍⠁⠗⠊⠕ (Mario Lang) on debian-devel


Re: Unsetting local variables

2017-03-17 Thread Martijn Dekker
Op 17-03-17 om 20:53 schreef Thorsten Glaser:
> Even mksh’s “global” builtin does not access the global scope.
> It’s simply a “typeset” that’s not also “local”.

But why the separate builtin (which is unique to mksh, if I'm not
mistaken) rather than 'typeset -g' as in zsh, bash 4 and yash?

Please consider adding 'typeset -g' as a synonym for 'global' for those
of us who target multiple shells:

Index: funcs.c
===
RCS file: /cvs/src/bin/mksh/funcs.c,v
retrieving revision 1.327
diff -u -r1.327 funcs.c
--- funcs.c 12 Mar 2017 02:31:26 -  1.327
+++ funcs.c 17 Mar 2017 21:42:39 -
@@ -784,7 +784,7 @@
}

/* see comment below regarding possible opions */
-   opts = istset ? "L#R#UZ#afi#lnprtux" : "p";
+   opts = istset ? "L#R#UZ#agfi#lnprtux" : "p";

builtin_opt.flags |= GF_PLUSOPT;
/*
@@ -829,6 +829,9 @@
case 'f':
func = true;
break;
+   case 'g':
+   localv = false;
+   break;
case 'i':
flag = INTEGER;
basestr = builtin_opt.optarg;
Index: mksh.1
===
RCS file: /cvs/src/bin/mksh/mksh.1,v
retrieving revision 1.427
diff -u -r1.427 mksh.1
--- mksh.1  12 Mar 2017 02:35:19 -  1.427
+++ mksh.1  17 Mar 2017 21:42:41 -
@@ -4803,7 +4803,7 @@
 .Pp
 .It Xo
 .Ic global
-.Oo Op Ic +\-alpnrtUux
+.Oo Op Ic +\-aglnprtUux
 .Op Fl L Ns Op Ar n
 .Op Fl R Ns Op Ar n
 .Op Fl Z Ns Op Ar n
@@ -4815,7 +4815,7 @@
 .Xc
 .It Xo
 .Ic typeset
-.Oo Op Ic +\-alpnrtUux
+.Oo Op Ic +\-aglnprtUux
 .Op Fl LRZ Ns Op Ar n
 .Op Fl i Ns Op Ar n
 .No \*(Ba Fl f Op Fl tux Oc
@@ -4880,6 +4880,11 @@
 .It Fl f
 Function mode.
 Display or set functions and their attributes, instead of parameters.
+.It Fl g
+Disable the local scope for parameters.
+Equivalent to using the
+.Ic global
+command.
 .It Fl i Ns Op Ar n
 Integer attribute.
 .Ar n



Re: Unsetting local variables

2017-03-17 Thread Dan Douglas
On 03/17/2017 12:07 PM, Stephane Chazelas wrote:
> Dan is describing what I can only explain as a bug or at least a
> very surprising feature:

The way Chet has described it in the past it sounded like an intentional
compromise to make outer scopes accessible without the also possibly
surprising interaction with outer scopes (which may be unpredictable
thanks to dynamic scope). But yes it isn't what you'd guess. It should
be documented at least.


Re: Unsetting local variables

2017-03-17 Thread Thorsten Glaser
Stephane Chazelas dixit:

>Because the "unset" was done in a separate function, instead of
>having an unset $a, we've got the $a of the outer scope.

Ouch. That’s extremely surprising.

By contrast, in mksh, there is simply no way, period, to get to
the global variable, or a variable from an intermediate scope,
if the local scope (or one below the intermediate but above the
local one) has hidden it.

Even mksh’s “global” builtin does not access the global scope.
It’s simply a “typeset” that’s not also “local”.

This was quite a thing to think about when introducing namerefs
to mksh, but I believe I found a way to make it work by convention:
every function in a nameref-using construct must prefix all locals
with its function name, so they never conflict. (That’s not to say
one cannot use namerefs without that, I do, e.g. in “uhr”, but e.g.
in a generic framework this is required.)

The idea behind this is probably: scopes can be nested (except ksh93),
and it doesn’t really make much sense to treat only one of the parent
scopes (the global one) special. In most programming languages, you
lose access to global names once you have a local one with the same
name.

bye,
//mirabilos
-- 
“ah that reminds me, thanks for the stellar entertainment that you and certain
other people provide on the Debian mailing lists │ sole reason I subscribed to
them (I'm not using Debian anywhere) is the entertainment factor │ Debian does
not strike me as a place for good humour, much less German admin-style humour”


Re: Unsetting local variables

2017-03-17 Thread Stephane Chazelas
2017-03-17 09:50:02 +0100, Jean Delvare:
[...]
> > It depends on context and the type of variable involved. Arrays complicate
> > things and namerefs _really_ complicate things. In bash, declaring a
> > simple local scalar, assigning it a value, then unsettling it within
> > the same scope brings the variable back to the same "hidden local"
> > state it is in when declared local but not given a value. However,
> > unsetting the local from a child scope does fully destroy the local,
> > uncovering the variables in parent scopes.
> 
> For the least educated of us, of which I am, can you explain what you
> mean by "child scope"?
[...]

Dan is describing what I can only explain as a bug or at least a
very surprising feature:

$ bash -c 'f() { local a=2; unset a; echo "$a"; }; a=1; f'

$

Above, the unset resulted in $a being unset in that scope. But:

$ bash -c 'u() { unset "$@"; }; f() { local a=2; u a; echo "$a"; }; a=1; f'
1

Because the "unset" was done in a separate function, instead of
having an unset $a, we've got the $a of the outer scope.

I think that's why Dan says it's more flexible. By using that
/bug/, one can get either one or the other behaviour.

-- 
Stephane



Re: Unsetting local variables

2017-03-17 Thread Jean Delvare
Hi Dan,

On Thu, 16 Mar 2017 14:30:06 -0500, Dan Douglas wrote:
> On 03/14/2017 05:08 AM, Jean Delvare wrote:
> > So internally bash does make a difference between a variable being
> > null and a variable being unset. A bash variable can actually have 4
> > distinct states: non-existent, existent but unset, set but null, and
> > non-null. "typeset", "local" and "unset" all put the variable into
> > state "existent but unset" (unlike mksh.)
> 
> It depends on context and the type of variable involved. Arrays complicate
> things and namerefs _really_ complicate things. In bash, declaring a
> simple local scalar, assigning it a value, then unsettling it within
> the same scope brings the variable back to the same "hidden local"
> state it is in when declared local but not given a value. However,
> unsetting the local from a child scope does fully destroy the local,
> uncovering the variables in parent scopes.

For the least educated of us, of which I am, can you explain what you
mean by "child scope"?

> Thus bash's is actually the most flexible of the dynamic scope systems
> in some ways. If you want bash to behave like mksh just define a wrapper
> function for unset (I usually name it `unset2'). Contrast with zsh,

What I needed was the opposite, and Thorsten helped me achieve that.

> which has no way to unset a local (last I checked, which was years
> ago). In addition, bash has `declare -g' for directly acting on the
> global scope. It has a few good uses e.g. for setting special variables
> like PATH or LC_*.

Thanks,
-- 
Jean Delvare
SUSE L3 Support


Re: Unsetting local variables

2017-03-16 Thread Dan Douglas
On 03/14/2017 05:08 AM, Jean Delvare wrote:
> So internally bash does make a difference between a variable being
> null and a variable being unset. A bash variable can actually have 4
> distinct states: non-existent, existent but unset, set but null, and
> non-null. "typeset", "local" and "unset" all put the variable into
> state "existent but unset" (unlike mksh.)

It depends on context and the type of variable involved. Arrays complicate
things and namerefs _really_ complicate things. In bash, declaring a
simple local scalar, assigning it a value, then unsettling it within
the same scope brings the variable back to the same "hidden local"
state it is in when declared local but not given a value. However,
unsetting the local from a child scope does fully destroy the local,
uncovering the variables in parent scopes.

Thus bash's is actually the most flexible of the dynamic scope systems
in some ways. If you want bash to behave like mksh just define a wrapper
function for unset (I usually name it `unset2'). Contrast with zsh,
which has no way to unset a local (last I checked, which was years
ago). In addition, bash has `declare -g' for directly acting on the
global scope. It has a few good uses e.g. for setting special variables
like PATH or LC_*.


Re: Unsetting local variables

2017-03-14 Thread Jean Delvare
Hallo Thorsten,

On Mon, 13 Mar 2017 18:20:11 + (UTC), Thorsten Glaser wrote:
> Jean Delvare dixit:
> 
> >A customer of ours has reported the following difference in behavior
> >between mksh and ksh-93: unsetting a local variable causes mksh to
> 
> Do note that ksh93 has static scoping, unlike ALL other shells
> which have hierarchical dynamic scoping comparable to other
> programming languages.
> 
> The scoping model in ksh93 is fundamentally incompatible to
> anything you know from anywhere else.

Yeah, the ksh93 variable scoping is... interestingly confusing.

> >destroy that local variable, so any further reference to its name will
> >relate to the global variable by the same name. Example:
> 
> Yes, that is correct. You can then “local” it again to
> recreate the local variable of said name.
> 
> >mksh will print 2, while ksh-93 will print 42. Note that bash will
> >print 42 as well, and so does dash after adjusting the shell syntax so
> >that dash understands it. So it seems that mksh handles this case
> >differently from all other shells.
> 
> Interesting… so it seems that GNU bash and dash don’t really
> unset it but only clean it.

Yes and no. See the difference between:

$ foo=
$ echo foo is ${foo+set}
foo is set

and:

$ unset foo
$ echo foo is ${foo+set}
foo is

So internally bash does make a difference between a variable being null
and a variable being unset. A bash variable can actually have 4 distinct
states: non-existent, existent but unset, set but null, and non-null.
"typeset", "local" and "unset" all put the variable into state
"existent but unset" (unlike mksh.)

Looking at the bash manual page, in most cases unset and null
are treated the same, however there are a few exceptions like the
example above (discovered by accident, doesn't appear to be documented)
or when you run bash with option -u.

> >I see that one can use "unset foo[*]" in mksh to achieve the "unset
> >foo" of other shells. I guess this is a side effect of the
> 
> You can? Hm, interesting… but makes sense.

Well I found it because it is documented in the man page, but the
syntax looks odd to me.

> >impossibility to preserve the variable attributes without preserving
> >the variable itself. But this doesn't really help anyway, as this
> >syntax is not portable.
> 
> if [[ $KSH_VERSION = *@(MIRBSD|LEGACY)\ KSH* ]]; then
>   function unset {
>   local __foo
> 
>   for __foo in "$@"; do
>   eval "unset $__foo[*]"
>   done
>   }
> fi

Does that actually work? It doesn't seem like special shell builtins
can be overloaded with functions, and unset is a special shell builtin.

> >So, is the behavior of unset on local variables a design decision, or
> 
> I believe the way mksh does it to be of the greatest benefit to
> the user, although I never actively decided either way. It *is*
> however what I’d expect when writing scripts.
> 
> (Note that pdksh also prints 2.)

I have to admit I was not sure myself what I would prefer as a script
author. I cowardly decided that unsetting local variables shouldn't be
needed, so I did not have to answer the question ;-)

However if I really had to make a choice... My initial feeling was that
mksh was right, as unset is exactly undoing the effect of typeset. But
my second thought was that it makes it way too easy to get things wrong
and accidentally access global variables. In particular, the fact that
calling "unset" twice on a local variable actually destroys the global
variable by the same name is kind of frightening.

In doubt, I guess I would have sticked to what other shells are doing,
for consistency. Ideally there would be an "unlocal" builtin to achieve
mksh's "unset" effect in functions. But then again I just can't figure
out a case where I would first declare a local variable and then want to
access a global variable by the same name instead.

-- 
Jean Delvare
SUSE L3 Support


Re: Unsetting local variables

2017-03-14 Thread Jean Delvare
On Mon, 13 Mar 2017 18:28:44 + (UTC), Thorsten Glaser wrote:
> Dixi quod…
> 
> >Jean Delvare dixit:
> >
> >>A customer of ours has reported the following difference in behavior
> >>between mksh and ksh-93
> 
> Do also note that it is not mksh’s goal to clone ksh93 and all of its
> behaviour, design decisions, etc.

Thank god :-D

This is perfectly understood and accepted, which is why I am asking
about the intent and your opinion and not bluntly reporting behavioral
divergences as bugs. And I keep repeating exactly the same to our
customers :-) So we are on the same track, no worry.

-- 
Jean Delvare
SUSE L3 Support


Re: Unsetting local variables

2017-03-13 Thread Stephane Chazelas
2017-03-13 18:20:11 +, Thorsten Glaser:
> Jean Delvare dixit:
> 
> >A customer of ours has reported the following difference in behavior
> >between mksh and ksh-93: unsetting a local variable causes mksh to
> 
> Do note that ksh93 has static scoping, unlike ALL other shells
> which have hierarchical dynamic scoping comparable to other
> programming languages.
[...]

Strictly speaking, there's also the "private" keyword in zsh for
static scoping (in zsh/param/private module).

-- 
Stephane



Re: Unsetting local variables

2017-03-13 Thread Thorsten Glaser
Dixi quod…

>Jean Delvare dixit:
>
>>A customer of ours has reported the following difference in behavior
>>between mksh and ksh-93

Do also note that it is not mksh’s goal to clone ksh93 and all of its
behaviour, design decisions, etc.

JFYI,
//mirabilos
-- 
I want one of these. They cost 720 € though… good they don’t have the HD hole,
which indicates 3½″ floppies with double capacity… still. A tad too much, atm.
‣ http://www.floppytable.com/floppytable-images-1.html


Re: Unsetting local variables

2017-03-13 Thread Thorsten Glaser
Jean Delvare dixit:

>A customer of ours has reported the following difference in behavior
>between mksh and ksh-93: unsetting a local variable causes mksh to

Do note that ksh93 has static scoping, unlike ALL other shells
which have hierarchical dynamic scoping comparable to other
programming languages.

The scoping model in ksh93 is fundamentally incompatible to
anything you know from anywhere else.

>destroy that local variable, so any further reference to its name will
>relate to the global variable by the same name. Example:

Yes, that is correct. You can then “local” it again to
recreate the local variable of said name.

>mksh will print 2, while ksh-93 will print 42. Note that bash will
>print 42 as well, and so does dash after adjusting the shell syntax so
>that dash understands it. So it seems that mksh handles this case
>differently from all other shells.

Interesting… so it seems that GNU bash and dash don’t really
unset it but only clean it.

>I see that one can use "unset foo[*]" in mksh to achieve the "unset
>foo" of other shells. I guess this is a side effect of the

You can? Hm, interesting… but makes sense.

>impossibility to preserve the variable attributes without preserving
>the variable itself. But this doesn't really help anyway, as this
>syntax is not portable.

if [[ $KSH_VERSION = *@(MIRBSD|LEGACY)\ KSH* ]]; then
function unset {
local __foo

for __foo in "$@"; do
eval "unset $__foo[*]"
done
}
fi

>So, is the behavior of unset on local variables a design decision, or

I believe the way mksh does it to be of the greatest benefit to
the user, although I never actively decided either way. It *is*
however what I’d expect when writing scripts.

(Note that pdksh also prints 2.)

bye,
//mirabilos
-- 
(gnutls can also be used, but if you are compiling lynx for your own use,
there is no reason to consider using that package)
-- Thomas E. Dickey on the Lynx mailing list, about OpenSSL


Unsetting local variables

2017-03-13 Thread Jean Delvare
Hi Thorsten,

A customer of ours has reported the following difference in behavior
between mksh and ksh-93: unsetting a local variable causes mksh to
destroy that local variable, so any further reference to its name will
relate to the global variable by the same name. Example:

#!/bin/ksh

function func2
{
typeset foo

unset foo
foo=2
}

foo=42
func2
echo "foo=$foo"

mksh will print 2, while ksh-93 will print 42. Note that bash will
print 42 as well, and so does dash after adjusting the shell syntax so
that dash understands it. So it seems that mksh handles this case
differently from all other shells.

I looked at the POSIX standard [1] but as I understand it POSIX doesn't
support local variables in the first place so the described behavior of
"unset" clearly refers to global variables and is subject to
interpretation for local variables.

I see that one can use "unset foo[*]" in mksh to achieve the "unset
foo" of other shells. I guess this is a side effect of the
impossibility to preserve the variable attributes without preserving
the variable itself. But this doesn't really help anyway, as this
syntax is not portable.

So, is the behavior of unset on local variables a design decision, or
an overlook?

[1] http://pubs.opengroup.org/onlinepubs/009695399/utilities/unset.html

Thanks,
-- 
Jean Delvare
SUSE L3 Support