zsh-users
 help / color / mirror / code / Atom feed
* A way to untie -T vars?
@ 2023-01-21 16:37 Sebastian Gniazdowski
  2023-01-21 16:55 ` Bart Schaefer
  2023-01-21 17:31 ` Bart Schaefer
  0 siblings, 2 replies; 29+ messages in thread
From: Sebastian Gniazdowski @ 2023-01-21 16:37 UTC (permalink / raw)
  To: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 321 bytes --]

Hi,
after:

local -T VAR var

doing:

unset var

unsets also VAR. The manual states this cannot be avoided. But maybe
there's a graceful way of untying the vars? I'm using -U flag to quickly
uniquify the scalar, however this method is problematic as the array vars
are left over.

-- 
Best regards,
Sebastian Gniazdowski

[-- Attachment #2: Type: text/html, Size: 1252 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 16:37 A way to untie -T vars? Sebastian Gniazdowski
@ 2023-01-21 16:55 ` Bart Schaefer
  2023-01-21 17:11   ` Bart Schaefer
  2023-01-21 17:15   ` Roman Perepelitsa
  2023-01-21 17:31 ` Bart Schaefer
  1 sibling, 2 replies; 29+ messages in thread
From: Bart Schaefer @ 2023-01-21 16:55 UTC (permalink / raw)
  To: Sebastian Gniazdowski; +Cc: Zsh Users

On Sat, Jan 21, 2023 at 8:38 AM Sebastian Gniazdowski
<sgniazdowski@gmail.com> wrote:
>
> maybe there's a graceful way of untying the vars?

There's not.

% typeset +T FOO
typeset: use unset to remove tied variables

> 'm using -U flag to quickly uniquify the scalar, however this method is problematic as the array vars are left over.

I don't follow what this is intended to accomplish?

% typeset -T FOO foo
% foo=(a b a c b e)
% typeset -U FOO
% print $foo
a b c e
%


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 16:55 ` Bart Schaefer
@ 2023-01-21 17:11   ` Bart Schaefer
  2023-01-21 18:52     ` Bart Schaefer
  2023-01-21 17:15   ` Roman Perepelitsa
  1 sibling, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-21 17:11 UTC (permalink / raw)
  To: Sebastian Gniazdowski; +Cc: Zsh Users

On Sat, Jan 21, 2023 at 8:55 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Sat, Jan 21, 2023 at 8:38 AM Sebastian Gniazdowski
> <sgniazdowski@gmail.com> wrote:
> >
> > maybe there's a graceful way of untying the vars?
>
> There's not.

There's this (unclear if "graceful"):

% typeset -a FOO=($FOO) foo=($foo)

This effectively unsets both variables and then immediately resets
them to their previous values ... except that it also converts the
scalar into a one-element array.  For most purposes that will work the
same, but not always.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 16:55 ` Bart Schaefer
  2023-01-21 17:11   ` Bart Schaefer
@ 2023-01-21 17:15   ` Roman Perepelitsa
  2023-01-21 17:23     ` Bart Schaefer
  1 sibling, 1 reply; 29+ messages in thread
From: Roman Perepelitsa @ 2023-01-21 17:15 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Sebastian Gniazdowski, Zsh Users

On Sat, Jan 21, 2023 at 5:56 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Sat, Jan 21, 2023 at 8:38 AM Sebastian Gniazdowski
> <sgniazdowski@gmail.com> wrote:
> >
> > 'm using -U flag to quickly uniquify the scalar, however this method is problematic as the array vars are left over.
>
> I don't follow what this is intended to accomplish?

While trying to understand what Sebastian meant I've accidentally
discovered an unorthodox way to unset a parameter.

    unset2() {
      local _"$1"
      typeset -gT _"$1" "$1"
    }

Test:

    % foo=hello
    % unset2 foo
    % typeset -p foo
    typeset: no such variable: foo

I sort of understand why that happens but it doesn't look intended.

Roman.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 17:15   ` Roman Perepelitsa
@ 2023-01-21 17:23     ` Bart Schaefer
  0 siblings, 0 replies; 29+ messages in thread
From: Bart Schaefer @ 2023-01-21 17:23 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Sebastian Gniazdowski, Zsh Users

On Sat, Jan 21, 2023 at 9:15 AM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
>     unset2() {
>       local _"$1"
>       typeset -gT _"$1" "$1"
>     }

Hm, yes, it's a bit weird to tie two variables that are in different
scopes.  This is vaguely related to the fix I applied to zsh/gdbm a
few months back to prevent local ztie from messing with the scope of a
database handle.

It ought to be possible to check for this and make that "typeset -gT"
into an error, if that's what we want to do.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 16:37 A way to untie -T vars? Sebastian Gniazdowski
  2023-01-21 16:55 ` Bart Schaefer
@ 2023-01-21 17:31 ` Bart Schaefer
  2023-01-21 17:48   ` Roman Perepelitsa
  1 sibling, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-21 17:31 UTC (permalink / raw)
  To: Sebastian Gniazdowski; +Cc: Zsh Users

On Sat, Jan 21, 2023 at 8:38 AM Sebastian Gniazdowski
<sgniazdowski@gmail.com> wrote:
>
> I'm using -U flag to quickly uniquify the scalar, however this method is problematic as the array vars are left over.

Oh, now I see what you mean.  You're adding an array with typeset -T
so that -U will remove duplicates from the scalar, but then you want
only the scalar to be left at the end -- the array is just a vehicle
for the "uniqueness" semantics.

Is using a tied array really that much faster than VAR=${(us.:.)VAR} ?


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 17:31 ` Bart Schaefer
@ 2023-01-21 17:48   ` Roman Perepelitsa
  2023-01-21 17:50     ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Roman Perepelitsa @ 2023-01-21 17:48 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Sebastian Gniazdowski, Zsh Users

On Sat, Jan 21, 2023 at 6:32 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Sat, Jan 21, 2023 at 8:38 AM Sebastian Gniazdowski
> <sgniazdowski@gmail.com> wrote:
> >
> > I'm using -U flag to quickly uniquify the scalar, however this method is problematic as the array vars are left over.
>
> Oh, now I see what you mean.  You're adding an array with typeset -T
> so that -U will remove duplicates from the scalar, but then you want
> only the scalar to be left at the end -- the array is just a vehicle
> for the "uniqueness" semantics.
>
> Is using a tied array really that much faster than VAR=${(us.:.)VAR} ?

A quick test shows that VAR=${(j.:.)${(us.:.)VAR}} is slightly faster
than `typeset -T VAR _VAR`. I could see it going either way depending
on the value and what exactly is being benchmarked, but the ballpark
performance should be the same.

Roman.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 17:48   ` Roman Perepelitsa
@ 2023-01-21 17:50     ` Bart Schaefer
  0 siblings, 0 replies; 29+ messages in thread
From: Bart Schaefer @ 2023-01-21 17:50 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Sebastian Gniazdowski, Zsh Users

On Sat, Jan 21, 2023 at 9:48 AM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> A quick test shows that VAR=${(j.:.)${(us.:.)VAR}} is slightly faster
> than `typeset -T VAR _VAR`.

I suspect we're missing some context -- e.g., perhaps new values are
repeatedly being appended to $VAR and it's slow to re-split the full
string every time?


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 17:11   ` Bart Schaefer
@ 2023-01-21 18:52     ` Bart Schaefer
  2023-01-21 19:15       ` Roman Perepelitsa
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-21 18:52 UTC (permalink / raw)
  To: Zsh Users

On Sat, Jan 21, 2023 at 9:11 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> % typeset -a FOO=($FOO) foo=($foo)

Speaking of unorthodoxy ...

% typeset -T FOO foo
% typeset foo=bar
typeset: foo: inconsistent type for assignment
% typeset -i foo=1
% typeset -p FOO foo
typeset: no such variable: FOO
typeset -i foo=1
%

So ... with "typeset" I can forcibly convert a tied scalar to an
array, or an array to an integer, but there's no way to convert an
array to an ordinary scalar.

Anyway ...

untie () {
  emulate -L zsh
  case ${(tP)1} in
  (scalar-tied)
    local scalar=${(P)1}
    unset $1
    typeset -g $1=$scalar
    ;;
  (array-tied)
    local array=( ${(P)1} )
    unset $1
    # Need eval here for array assignment, as
    # reserved word doesn't work with $1=(...)
    eval "typeset -ga $1=( \$array )"
    ;;
  (*) ;;
  esac
}


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 18:52     ` Bart Schaefer
@ 2023-01-21 19:15       ` Roman Perepelitsa
  2023-01-22  9:34         ` Pier Paolo Grassi
  0 siblings, 1 reply; 29+ messages in thread
From: Roman Perepelitsa @ 2023-01-21 19:15 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On Sat, Jan 21, 2023 at 7:53 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> Speaking of unorthodoxy ...
>
> untie () {
>   emulate -L zsh
>   case ${(tP)1} in
>   (scalar-tied)
>     local scalar=${(P)1}
>     unset $1
>     typeset -g $1=$scalar
>     ;;
>   (array-tied)
>     local array=( ${(P)1} )
>     unset $1
>     # Need eval here for array assignment, as
>     # reserved word doesn't work with $1=(...)
>     eval "typeset -ga $1=( \$array )"
>     ;;
>   (*) ;;
>   esac
> }

Bravo.

`untie scalar` and `untie array` won't work due to name clashes but
this seems easily fixable.

Roman.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-21 19:15       ` Roman Perepelitsa
@ 2023-01-22  9:34         ` Pier Paolo Grassi
  2023-01-22  9:58           ` Roman Perepelitsa
  0 siblings, 1 reply; 29+ messages in thread
From: Pier Paolo Grassi @ 2023-01-22  9:34 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Bart Schaefer, Zsh Users

[-- Attachment #1: Type: text/plain, Size: 993 bytes --]

and what your solution could look like? I would use something like
___untie_array and ___untie_scalar that I would never use outside the untie
function, but I wonder if there is a more general solution

Il giorno sab 21 gen 2023 alle 20:16 Roman Perepelitsa <
roman.perepelitsa@gmail.com> ha scritto:

> On Sat, Jan 21, 2023 at 7:53 PM Bart Schaefer <schaefer@brasslantern.com>
> wrote:
> >
> > Speaking of unorthodoxy ...
> >
> > untie () {
> >   emulate -L zsh
> >   case ${(tP)1} in
> >   (scalar-tied)
> >     local scalar=${(P)1}
> >     unset $1
> >     typeset -g $1=$scalar
> >     ;;
> >   (array-tied)
> >     local array=( ${(P)1} )
> >     unset $1
> >     # Need eval here for array assignment, as
> >     # reserved word doesn't work with $1=(...)
> >     eval "typeset -ga $1=( \$array )"
> >     ;;
> >   (*) ;;
> >   esac
> > }
>
> Bravo.
>
> `untie scalar` and `untie array` won't work due to name clashes but
> this seems easily fixable.
>
> Roman.
>
> --
Pier Paolo Grassi

[-- Attachment #2: Type: text/html, Size: 1635 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-22  9:34         ` Pier Paolo Grassi
@ 2023-01-22  9:58           ` Roman Perepelitsa
  2023-01-23  2:14             ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Roman Perepelitsa @ 2023-01-22  9:58 UTC (permalink / raw)
  To: Pier Paolo Grassi; +Cc: Bart Schaefer, Zsh Users

On Sun, Jan 22, 2023 at 10:34 AM Pier Paolo Grassi <pierpaolog@gmail.com> wrote:
>
> and what your solution could look like? I would use something like
> ___untie_array and ___untie_scalar that I would never use outside
> the untie function, but I wonder if there is a more general solution

Something like this:

    untie() {
      emulate -L zsh
      case ${(tP)1} in
      (scalar-tied)
        set -- $1 ${(P)1}
        unset $1
        typeset -g $1=$2
        ;;
      (array-tied)
        set -- $1 "${(@P)1}"
        unset $1
        set -A "$@"
        ;;
      (*) ;;
      esac
    }

Positional parameters already shadow same-name parameters from the
caller, so we can safely use them for locals.

I've made one unrelated change here: replaced `eval` with `set -A`. It
looks simpler, and incidentally fixes a bug with the handling of empty
elements.

If you wanted to turn this into a library function, you would need to
handle more types. Things like array-local-tied (simply ignore
"local") and scalar-tied-export (make sure to export the scalar). This
should be straightforward.

Roman.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-22  9:58           ` Roman Perepelitsa
@ 2023-01-23  2:14             ` Bart Schaefer
  2023-01-23  9:47               ` Roman Perepelitsa
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-23  2:14 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Pier Paolo Grassi, Zsh Users

On Sun, Jan 22, 2023 at 1:58 AM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> If you wanted to turn this into a library function, you would need to
> handle more types.

So ... (gmail is probably going to line-wrap this)

untie () {
  emulate -L zsh
  while ((ARGC))
  do
    () {
      case ${(tP)1} in
        (array-tied) set -- $1 "${(@P)1}"
          unset $1
          set -A "$@" ;;
        (scalar-tied-export) set -- $1 x ;&
        (scalar-tied) set -- $1 ${(P)1} $2
          unset $1
          typeset -g$3 $1=$2 ;;
        (*tied*) print -u2 -r "Can't untie ${(qqq)1}: ${(tP)1}" ;;
        (*) : "${(qqq)1}: not a tied parameter" ;;
      esac
    } $1
    shift
  done
}

The (*) label is for benefit of xtrace, but it could instead print
that message.  I couldn't find any other parameter types that needed
handling?

That's "functions -x2" output, by the way, take it up with PWS if you
don't like the placement of the case labels/delimiters.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-23  2:14             ` Bart Schaefer
@ 2023-01-23  9:47               ` Roman Perepelitsa
  2023-01-23 18:27                 ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Roman Perepelitsa @ 2023-01-23  9:47 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Pier Paolo Grassi, Zsh Users

On Mon, Jan 23, 2023 at 3:14 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Sun, Jan 22, 2023 at 1:58 AM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> > If you wanted to turn this into a library function, you would need to
> > handle more types.
>
> [...] I couldn't find any other parameter types that needed
> handling?

There are a few more things that could be handled by untie().

    () {
      local -hHtUT FOO foo
      print -rC1 -- ${(t)foo}
    }

Here foo is array-local-tag-tied-unique-hide-hideval. I believe it can
be untied and become array-local-tag-unique-hide-hideval (only "tied"
is gone).

Roman.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-23  9:47               ` Roman Perepelitsa
@ 2023-01-23 18:27                 ` Bart Schaefer
  2023-01-23 18:42                   ` Mikael Magnusson
  2023-01-24  5:45                   ` Bart Schaefer
  0 siblings, 2 replies; 29+ messages in thread
From: Bart Schaefer @ 2023-01-23 18:27 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Pier Paolo Grassi, Zsh Users

On Mon, Jan 23, 2023 at 1:47 AM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> Here foo is array-local-tag-tied-unique-hide-hideval. I believe it can
> be untied and become array-local-tag-unique-hide-hideval (only "tied"
> is gone).

Hm.

As best I can tell:

array local left justified 10 zero filled 10 uppercase tagged unique
tied FOO foo

(plus export, hide, and hideval, which typeset +m does not display) is
the largest possible set of type fields for a tied pair.  If "left" is
replaced by "right" you can't have "zero filled", and "uppercase"
could be replaced only by "lowercase".

Of course the ${(t)FOO} words are not the same and don't include the size data.

scalar-local-left-right_zeros-lower-tag-tied-export-unique-hide-hideval

Also, although you can assign justification/filling to a tied pair,
none of it actually applies when expanding the array elements, so it's
questionable whether "untie" needs to preserve it for the array.  I
suppose in Sebastian's use case, it should?

Another interesting note, "typeset -x" implies "-g" but "local -x" does not.

Pondering.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-23 18:27                 ` Bart Schaefer
@ 2023-01-23 18:42                   ` Mikael Magnusson
  2023-01-23 18:43                     ` Mikael Magnusson
  2023-01-23 19:12                     ` Bart Schaefer
  2023-01-24  5:45                   ` Bart Schaefer
  1 sibling, 2 replies; 29+ messages in thread
From: Mikael Magnusson @ 2023-01-23 18:42 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Roman Perepelitsa, Pier Paolo Grassi, Zsh Users

On 1/23/23, Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Mon, Jan 23, 2023 at 1:47 AM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
>>
>> Here foo is array-local-tag-tied-unique-hide-hideval. I believe it can
>> be untied and become array-local-tag-unique-hide-hideval (only "tied"
>> is gone).
>
> Hm.
>
> Another interesting note, "typeset -x" implies "-g" but "local -x" does
> not.

There's no way it could imply it, since local -g doesn't accept -g, so
you would have to argue why typeset -x should not imply it (and do it
like 30 years ago) :).

Checked the manpage and it says export is equivalent to typeset -gx,
which is true, but we could save a byte by removing that g.

Also local says this:
  Same  as  typeset,  except that the options -g, and -f are not permitted.  In
  this case the -x option does not force the use of -g, i.e. exported variables
  will be local to functions.

which does not seem to be true; typeset -x does not force -g, it is
implied by default but you can use +g to disable it again:

% bar=outside; () { typeset -x +g bar=baz; env | grep bar=baz }; echo $bar
bar=baz
outside

without the +g, the second line output is "baz" (obviously).

The entry for typeset itself correctly states:
  If the option GLOBAL_EXPORT is set, this implies the option -g,
unless  +g is also explicitly given; in other words the parameter is
not made local to the enclosing function.  This is for  compatibility
with previous versions of zsh.

Not sure if it's worth clarifying the point under "local"?

Also for maximum confusion, GLOBAL_EXPORT doesn't affect the behavior
of "export", that always forces (not implies) both -x and -g:
% export +x foo
export: bad option: +x
% export +g foo
export: bad option: +g
but with GLOBAL_EXPORT unset, my example above prints "outside" on the
second line even without the +g.

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-23 18:42                   ` Mikael Magnusson
@ 2023-01-23 18:43                     ` Mikael Magnusson
  2023-01-23 19:12                     ` Bart Schaefer
  1 sibling, 0 replies; 29+ messages in thread
From: Mikael Magnusson @ 2023-01-23 18:43 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Roman Perepelitsa, Pier Paolo Grassi, Zsh Users

On 1/23/23, Mikael Magnusson <mikachu@gmail.com> wrote:
> On 1/23/23, Bart Schaefer <schaefer@brasslantern.com> wrote:
>> On Mon, Jan 23, 2023 at 1:47 AM Roman Perepelitsa
>> <roman.perepelitsa@gmail.com> wrote:
>>>
>>> Here foo is array-local-tag-tied-unique-hide-hideval. I believe it can
>>> be untied and become array-local-tag-unique-hide-hideval (only "tied"
>>> is gone).
>>
>> Hm.
>>
>> Another interesting note, "typeset -x" implies "-g" but "local -x" does
>> not.
>
> There's no way it could imply it, since local -g doesn't accept -g, so
> you would have to argue why typeset -x should not imply it (and do it
> like 30 years ago) :).
>
> Checked the manpage and it says export is equivalent to typeset -gx,
> which is true, but we could save a byte by removing that g.

Noticed just after sending, but technically not true, typeset -gx +gx
is allowed, whereas export +x as noted previously is not.

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-23 18:42                   ` Mikael Magnusson
  2023-01-23 18:43                     ` Mikael Magnusson
@ 2023-01-23 19:12                     ` Bart Schaefer
  1 sibling, 0 replies; 29+ messages in thread
From: Bart Schaefer @ 2023-01-23 19:12 UTC (permalink / raw)
  To: Mikael Magnusson; +Cc: Roman Perepelitsa, Pier Paolo Grassi, Zsh Users

On Mon, Jan 23, 2023 at 10:42 AM Mikael Magnusson <mikachu@gmail.com> wrote:
>
> On 1/23/23, Bart Schaefer <schaefer@brasslantern.com> wrote:
> > Another interesting note, "typeset -x" implies "-g" but "local -x" does
> > not.
>
> There's no way it could imply it, since local -g doesn't accept -g, so
> you would have to argue why typeset -x should not imply it (and do it
> like 30 years ago) :).

One of those things I'd forgotten:  it breaks the usual equivalence of
"typeset" and "local" when occurring in function context.

Now that I think of it, I haven't checked "declare".


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-23 18:27                 ` Bart Schaefer
  2023-01-23 18:42                   ` Mikael Magnusson
@ 2023-01-24  5:45                   ` Bart Schaefer
  2023-01-24  9:56                     ` Roman Perepelitsa
  1 sibling, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-24  5:45 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Pier Paolo Grassi, Zsh Users

[-- Attachment #1: Type: text/plain, Size: 1201 bytes --]

On Mon, Jan 23, 2023 at 10:27 AM Bart Schaefer
<schaefer@brasslantern.com> wrote:
>
> array local left justified 10 zero filled 10 uppercase tagged unique
> tied FOO foo
>
> (plus export, hide, and hideval, which typeset +m does not display)

Minor correction:  typeset +m does output "exported" for scalars, but
not for arrays even when tied to an exported scalar.

> Pondering.

I've reached the conclusion that "local" makes no difference here.  If
any calling scope has declared the parameter local, it will remain
local to that scope even if unset, and the dynamic scope behavior of
"typeset -g" from inside "untie" will apply to the variable in that
scope.

Also, per the other thread, there's no way to get the justification
width for -L/-R/-Z without using typeset +m so that's what I've done.
Since -L and -Z may be specified together, I've made two calls to
typeset +m, the gyrations to reduce it to a single call seemed even
more confusing than the hoops necessary to shuffle all the switches
through the positional parameters.

Attached this time because I'm sure gmail would maim it.  This has
been tested with convoluted cases, but not with simple ones, so it may
still need refinement.

[-- Attachment #2: untie.txt --]
[-- Type: text/plain, Size: 1342 bytes --]

untie () {
  emulate -L zsh -o extendedglob -o errreturn
  while ((ARGC))
  do
    () {
      case ${(tP)1} in
        (*right_zeros*) set -- $1 -Z${${(M@)$(typeset +m $1):#[[:digit:]]#}[1]} ;;
      esac
      case ${(tP)1} in
        (*left*) set -- "$@" -L${${(M@)$(typeset +m $1):#[[:digit:]]#}[1]} ;;
        (*right_blanks*) set -- "$@" -R${${(M@)$(typeset +m $1):#[[:digit:]]#}[1]} ;;
      esac
      if [[ ${(tP)1} = *export* ]]
      then
        set -- $1 -x ${argv[2,$#]}
      else
        set -- $1 -g ${argv[2,$#]}
      fi
      set ${(s:-:tP)1} - $1 ${argv[2,$#]}
      while [[ $1 != - ]]
      do
        case $1 in
          (tag) set -- "$@" -t ;;
          (unique) set -- "$@" -U ;;
          (upper) set -- "$@" -u ;;
          (lower) set -- "$@" -l ;;
          (hide) set -- "$@" -h ;;
          (hideval) set -- "$@" -H ;;
        esac
        shift
      done
      shift
      case ${(tP)1} in
        (array*tied*) set -- $1 $# "$@" $1 "${(@P)1}"
          unset $1
          typeset -a ${argv[4,$2+2]} $1
          shift $2+2
          set -A "$@" ;;
        (scalar*tied*) set -- "$@" $1=${(P)1}
          unset $1
          shift
          typeset "$@" ;;
        (*tied*) print -u2 -r "Can't untie ${(qqq)1}: ${(tP)1}" ;;
        (*) : "${1}: not a tied parameter" ;;
      esac
    } $1
    shift
  done
}

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-24  5:45                   ` Bart Schaefer
@ 2023-01-24  9:56                     ` Roman Perepelitsa
  2023-01-24 16:42                       ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Roman Perepelitsa @ 2023-01-24  9:56 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Pier Paolo Grassi, Zsh Users

On Tue, Jan 24, 2023 at 6:45 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> I've reached the conclusion that "local" makes no difference here.

I actually knew that! There is no way to remove a parameter from a
scope. Once a name is added to a scope, it stays there forever (until
the whole scope dies) and a lookup for the name will always stop on
this scope.

> Attached this time because I'm sure gmail would maim it.  This has
> been tested with convoluted cases, but not with simple ones, so it may
> still need refinement.

LGTM. I'm a bit paranoid about matching words such as "tied" without
anchors. If in the future we get type keywords that have these as
substrings ("guarantied"), this code will break.

The fact that this function has to fork diminishes its applicability greatly.

Up until this thread I thought that `bindkey` was the only builtin
that printed information that is otherwise unobtainable: retrieving
bindings requires forking or file I/O. Now `typeset +m` can be added
to the list: retrieving the type of a parameter also requires forking
or file I/O.

Roman.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-24  9:56                     ` Roman Perepelitsa
@ 2023-01-24 16:42                       ` Bart Schaefer
  2023-01-24 16:45                         ` Peter Stephenson
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-24 16:42 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Pier Paolo Grassi, Zsh Users

On Tue, Jan 24, 2023 at 1:56 AM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> LGTM. I'm a bit paranoid about matching words such as "tied" without
> anchors. If in the future we get type keywords that have these as
> substrings ("guarantied"), this code will break.

"...  guaranty refers specifically to a written agreement that one
party will pay the money required if another party fails to do so."

I don't think we're going to have any guarantied parameters. :-)
Guaranteed, maybe.

> The fact that this function has to fork diminishes its applicability greatly.

Circumstances in which a tied variable has text justification settings
should be quite rare, the forks only happen then.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-24 16:42                       ` Bart Schaefer
@ 2023-01-24 16:45                         ` Peter Stephenson
  2023-01-24 17:40                           ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Peter Stephenson @ 2023-01-24 16:45 UTC (permalink / raw)
  To: Zsh Users

> On 24/01/2023 16:42 Bart Schaefer <schaefer@brasslantern.com> wrote:
> I don't think we're going to have any guarantied parameters. :-)
> Guaranteed, maybe.

"Use of shell language by users voids guarantee".

pws


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-24 16:45                         ` Peter Stephenson
@ 2023-01-24 17:40                           ` Bart Schaefer
  2023-01-24 17:54                             ` Roman Perepelitsa
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-24 17:40 UTC (permalink / raw)
  To: Zsh Users

On Tue, Jan 24, 2023 at 8:45 AM Peter Stephenson
<p.w.stephenson@ntlworld.com> wrote:
>
> > On 24/01/2023 16:42 Bart Schaefer <schaefer@brasslantern.com> wrote:
> > I don't think we're going to have any guarantied parameters. :-)
> > Guaranteed, maybe.
>
> "Use of shell language by users voids guarantee".

There are only 14 words containing "tied" in /usr/share/dict/words on
my desktop, and a quick scan of words ending in "ty|tie" doesn't yield
many that can be "tied", and none except "untied" seem likely to ever
apply.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-24 17:40                           ` Bart Schaefer
@ 2023-01-24 17:54                             ` Roman Perepelitsa
  2023-01-24 22:54                               ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Roman Perepelitsa @ 2023-01-24 17:54 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On Tue, Jan 24, 2023 at 6:41 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Tue, Jan 24, 2023 at 8:45 AM Peter Stephenson
> <p.w.stephenson@ntlworld.com> wrote:
> >
> > > On 24/01/2023 16:42 Bart Schaefer <schaefer@brasslantern.com> wrote:
> > > I don't think we're going to have any guarantied parameters. :-)
> > > Guaranteed, maybe.
> >
> > "Use of shell language by users voids guarantee".
>
> There are only 14 words containing "tied" in /usr/share/dict/words on
> my desktop, and a quick scan of words ending in "ty|tie" doesn't yield
> many that can be "tied", and none except "untied" seem likely to ever
> apply.

There is also "array", "scalar" and "left" in the code with a similar
assumption about the future keywords.

If I were writing this code, I would change it without computing
probabilities because it feels wrong to me. I've learned this specific
pitfall a long time ago and since then it jumps out at me when I see
it in someone's code. The fix is fairly simple and would make the code
more explicit, hence easier to understand. It'll be clear that we are
checking for "left" and not for any keyword that contains "left".
Right now I actually don't know what that line does and if there are
keywords that contain "left" but aren't equal to it.

Roman.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-24 17:54                             ` Roman Perepelitsa
@ 2023-01-24 22:54                               ` Bart Schaefer
  2023-01-25 14:41                                 ` Roman Perepelitsa
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-24 22:54 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 1012 bytes --]

On Tue, Jan 24, 2023 at 1:56 AM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> On Tue, Jan 24, 2023 at 6:45 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
> >
> > I've reached the conclusion that "local" makes no difference here.
>
> I actually knew that! There is no way to remove a parameter from a
> scope. Once a name is added to a scope, it stays there forever

Turns out that such a name also retains its justification settings
when unset, so there's no need to resort to typeset +m to reassert
them.

On Tue, Jan 24, 2023 at 9:55 AM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> If I were writing this code, I would change it without computing
> probabilities because it feels wrong to me.

Given the foregoing about justification there are a number of things
about the previously-attached "untie" that can be streamlined, so this
mostly became a non-issue.

In this replacement variant, the readonly|special branch could become
a fatal error (return 1) if that's preferred.

[-- Attachment #2: untie.txt --]
[-- Type: text/plain, Size: 1220 bytes --]

untie () {
  emulate -L zsh -o extendedglob -o errreturn
  while ((ARGC))
  do
    () {
      case -${(tP)1}- in
        (*-(readonly|special)-*) print -u2 -r "Can't untie ${(qqq)1}: ${(tP)1}"
          return 0 ;;
        (*-tied-*) set -- ${(s:-:tP)1} - $1 -g ;;
        (*) : "${1}: not a tied parameter"
          return 0 ;;
      esac
      while [[ $1 != - ]]
      do
        case $1 in
          (export) set -- "$@" -x ;;
          (tag) set -- "$@" -t ;;
          (unique) set -- "$@" -U ;;
          (upper) set -- "$@" -u ;;
          (lower) set -- "$@" -l ;;
          (hide) set -- "$@" -h ;;
          (hideval) set -- "$@" -H ;;
          (left) set -- "$@" -L ;;
          (right_blanks) set -- "$@" -R ;;
          (right_zeros) set -- "$@" -Z ;;
        esac
        shift
      done
      shift
      case -${(tP)1}- in
        (*-array-*) set -- $# "$@" $1 "${(@P)1}"
          unset $2
          typeset -a ${argv[3,$1+1]} $2
          shift $1+1
          set -A "$@" ;;
        (*-scalar-*) set -- "$@" $1=${(P)1}
          unset $1
          shift
          typeset "$@" ;;
        (*) print -u2 -r -- "${1}: impossible: ${(tP)1}"
          return 1 ;;
      esac
    } $1
    shift
  done
}

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-24 22:54                               ` Bart Schaefer
@ 2023-01-25 14:41                                 ` Roman Perepelitsa
  2023-01-25 22:39                                   ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Roman Perepelitsa @ 2023-01-25 14:41 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On Tue, Jan 24, 2023 at 11:54 PM Bart Schaefer
<schaefer@brasslantern.com> wrote:
>
> On Tue, Jan 24, 2023 at 1:56 AM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> > On Tue, Jan 24, 2023 at 6:45 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
> > >
> > > I've reached the conclusion that "local" makes no difference here.
> >
> > I actually knew that! There is no way to remove a parameter from a
> > scope. Once a name is added to a scope, it stays there forever
>
> Turns out that such a name also retains its justification settings
> when unset

That sounds surprising. Is this actually so?

    % () {
      typeset -L3 foo
      typeset -p foo
      unset foo
      typeset foo
      typeset -p foo
    }

    typeset -L3 foo=''
    typeset foo=''

Here unset + typeset removed justification, as I would expect. Am I
misunderstanding what you meant?

Roman.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-25 14:41                                 ` Roman Perepelitsa
@ 2023-01-25 22:39                                   ` Bart Schaefer
  2023-01-25 23:48                                     ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-25 22:39 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh Users

On Wed, Jan 25, 2023 at 6:42 AM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> On Tue, Jan 24, 2023 at 11:54 PM Bart Schaefer
> <schaefer@brasslantern.com> wrote:
> >
> > Turns out that such a name also retains its justification settings
> > when unset
>
> That sounds surprising. Is this actually so?

Well, dash it all, this what comes of my only testing on complicated
cases.  The justification for -L/-R/-Z when not specified is intuited
from the value assigned to the variable, not inherited from the
previous scope as it appeared from what I was using as test inputs.

So those $(typeset +m ...) are going to have to come back, in some form.  Bleah.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-25 22:39                                   ` Bart Schaefer
@ 2023-01-25 23:48                                     ` Bart Schaefer
  2023-01-26  2:34                                       ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2023-01-25 23:48 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh Users

On Wed, Jan 25, 2023 at 2:39 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> The justification for -L/-R/-Z when not specified is intuited
> from the value assigned to the variable, not inherited

Ah ha ha.  Ha ha.  Ha.

The value being assigned to the variable is coming from $1=${(P)1} and
${(P)1} includes the specified justification, so the value assigned is
always already the correct width.

The main issue with this would be for zero-filling when referenced in
math context with OCTAL_ZEROES.  Is there any other way to reference
the "real, unfilled" value of a parameter that has justification
specified?  The latter would need to be used in the untie function
itself, if possible.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: A way to untie -T vars?
  2023-01-25 23:48                                     ` Bart Schaefer
@ 2023-01-26  2:34                                       ` Bart Schaefer
  0 siblings, 0 replies; 29+ messages in thread
From: Bart Schaefer @ 2023-01-26  2:34 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 767 bytes --]

On Wed, Jan 25, 2023 at 3:48 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> The value being assigned to the variable is coming from $1=${(P)1} and
> ${(P)1} includes the specified justification, so the value assigned is
> always already the correct width.

Which means ${(P)#1} is the justification, no need to fork typeset for
that, and ...

> Is there any other way to reference
> the "real, unfilled" value of a parameter that has justification
> specified?

The only reliable way I can find is to first remove the justification:

% typeset -L5 FOO=123456789
% printf "<%s>\n" $FOO
<12345>
% typeset +L FOO
% printf "<%s>\n" $FOO
<123456789>

This can be done without otherwise changing the type or tied-ness of the scalar.

One more pass at it attached.

[-- Attachment #2: untie.txt --]
[-- Type: text/plain, Size: 1315 bytes --]

untie () {
  emulate -L zsh -o extendedglob -o errreturn
  while ((ARGC))
  do
    () {
      case -${(tP)1}- in
        (*-(readonly|special)-*) print -u2 -r "Can't untie ${(qqq)1}: ${(tP)1}"
          return 0 ;;
        (*-tied-*) set -- ${(s:-:tP)1} - $1 -g ;;
        (*) : "${1}: not a tied parameter"
          return 0 ;;
      esac
      while [[ $1 != - ]]
      do
        case $1 in
          (export) set -- "$@" -x ;;
          (tag) set -- "$@" -t ;;
          (unique) set -- "$@" -U ;;
          (upper) set -- "$@" -u ;;
          (lower) set -- "$@" -l ;;
          (hide) set -- "$@" -h ;;
          (hideval) set -- "$@" -H ;;
          (left) set -- "$@" -L${(P)#${@[$@[(i)-]+1]}} ;;
          (right_blanks) set -- "$@" -R${(P)#${@[$@[(i)-]+1]}} ;;
          (right_zeros) set -- "$@" -Z${(P)#${@[$@[(i)-]+1]}} ;;
        esac
        shift
      done
      shift
      case -${(tP)1}- in
        (*-array-*) set -- $# "$@" $1 "${(@P)1}"
          unset $2
          typeset -a ${argv[3,$1+1]} $2
          shift $1+1
          set -A "$@" ;;
        (*-scalar-*) typeset -g +L +R +Z $1
	  set -- "$@" $1=${(P)1}
          unset $1
          shift
          typeset "$@" ;;
        (*) print -u2 -r -- "${1}: impossible: ${(tP)1}"
          return 1 ;;
      esac
    } $1
    shift
  done
}

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2023-01-26  2:35 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-21 16:37 A way to untie -T vars? Sebastian Gniazdowski
2023-01-21 16:55 ` Bart Schaefer
2023-01-21 17:11   ` Bart Schaefer
2023-01-21 18:52     ` Bart Schaefer
2023-01-21 19:15       ` Roman Perepelitsa
2023-01-22  9:34         ` Pier Paolo Grassi
2023-01-22  9:58           ` Roman Perepelitsa
2023-01-23  2:14             ` Bart Schaefer
2023-01-23  9:47               ` Roman Perepelitsa
2023-01-23 18:27                 ` Bart Schaefer
2023-01-23 18:42                   ` Mikael Magnusson
2023-01-23 18:43                     ` Mikael Magnusson
2023-01-23 19:12                     ` Bart Schaefer
2023-01-24  5:45                   ` Bart Schaefer
2023-01-24  9:56                     ` Roman Perepelitsa
2023-01-24 16:42                       ` Bart Schaefer
2023-01-24 16:45                         ` Peter Stephenson
2023-01-24 17:40                           ` Bart Schaefer
2023-01-24 17:54                             ` Roman Perepelitsa
2023-01-24 22:54                               ` Bart Schaefer
2023-01-25 14:41                                 ` Roman Perepelitsa
2023-01-25 22:39                                   ` Bart Schaefer
2023-01-25 23:48                                     ` Bart Schaefer
2023-01-26  2:34                                       ` Bart Schaefer
2023-01-21 17:15   ` Roman Perepelitsa
2023-01-21 17:23     ` Bart Schaefer
2023-01-21 17:31 ` Bart Schaefer
2023-01-21 17:48   ` Roman Perepelitsa
2023-01-21 17:50     ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).