zsh-workers
 help / color / mirror / code / Atom feed
* Re: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-16 11:50 Sven Wischnowsky
  1999-03-25 12:00 ` ${...:-...} again and subst clarification E: " Andrej Borsenkow
  0 siblings, 1 reply; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-16 11:50 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> >   The behavior is a bit weird, though, because `${foo-bar}' uses
> >   `multsub', too. I haven't changed the call to it, yet, so the result 
> >   is that the `bar' is broken into an array -- always. This means that 
> >   `${#:-$foo}' will yield `1' for strings and the number of elements
> >   if `bar' is `$baz' where `baz' is an array. I didn't change it
> >   because I wanted to ask what it should do first, suggestions are:
> > 
> >   1) let it treat the `bar' always as a string (i.e. let it never be
> >      split into array elements); I guess this is what most people
> >      would expect (and in the manual the thing is called `word')
> 
> Since (without shwordsplit)
> 
>   % args() { print $#; }
>   % args ${foo:-foo bar}
>   1
> 
> this is the natural thing to do.

I liked this one best, too, so the patch below implements it.

> >   2) like 1), but if combined with the `A' flag, let it be treated as
> >      an array
> 
> Some extension like this is reasonable, but the obvious candidate is
> ${(w)#:-foo bar}, which is supposed to have exactly this effect on $# for a
> string.
> 
>  % foo="foo bar"
>  % print ${(w)#foo}
>  2

Right, hadn't thought of that.

Bye
 Sven

--- os/subst.c	Mon Mar 15 10:52:31 1999
+++ Src/subst.c	Tue Mar 16 12:46:13 1999
@@ -1273,7 +1273,7 @@
 	case '-':
 	    if (vunset) {
 		val = dupstring(s);
-		multsub(&val, &aval, &isarr, NULL);
+		multsub(&val, NULL, &isarr, NULL);
 		copied = 1;
 	    }
 	    break;

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* ${...:-...} again and subst clarification E: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
  1999-03-16 11:50 PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter Sven Wischnowsky
@ 1999-03-25 12:00 ` Andrej Borsenkow
  0 siblings, 0 replies; 12+ messages in thread
From: Andrej Borsenkow @ 1999-03-25 12:00 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

> > >
> > >   1) let it treat the `bar' always as a string (i.e. let it never be
> > >      split into array elements); I guess this is what most people
> > >      would expect (and in the manual the thing is called `word')
> >

I just found, that ${...:-...} does not work with arrays at all

bor@itsrm2:~%> foo=()
bor@itsrm2:~%> bar=(c d)
bor@itsrm2:~%> args ${foo:-${bar}}
0
bor@itsrm2:~%> args ${foo-${bar}}
0

If this was intended, then this change is really O.K and does the right
thing. But then, it should explicitly be mentioned in manuals.

The same applies to words after %, #, /, = (without (A)) and to val in
FOO=val as well. In all these contexts array value is forced (joined) to
scalar. May be, it is needed to be explicitly stated as well (to avoid
confusion). ${...=...} case is mentioned - but, probably, it would be better
to have them explained in rules in the correct place - even more so, as the
way it is done is again inconsistent:

bor@itsrm2:~%> setopt shwordsplit
bor@itsrm2:~%> IFS="$IFS:"
bor@itsrm2:~%> foo=("x:y" "a:b")
bor@itsrm2:~%> bar=$foo
bor@itsrm2:~%> print "$bar"
x:y a:b

No word splitting. The same applies to #, % and /.

bor@itsrm2:~%> yyy=${xxx:-$foo}
bor@itsrm2:~%> print "$yyy"
x y a b

$foo is wordsplitted. the same with =.

cheers

/andrej


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

* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-17 14:59 Sven Wischnowsky
  0 siblings, 0 replies; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-17 14:59 UTC (permalink / raw)
  To: zsh-workers


Andrej Borsenkow wrote:

> > It's actually completely predictable, once you know the rule.
> >
> 
> 'course. What I tried to explain, that there is probably a dozen of people,
> who know these rules :-( (correct me if I'm wrong)
> 
> O.K. Is it intentional?
> 
> itsrm2% foo=(axb cxd)
> itsrm2% print -l ${(s/x/)foo}
> a
> b c
> d
> 
> I won't argue, if this is correct or not. I'd just to point out
> a) if this is intentional, it should be documented
> b) it is very different from word splitting (which is referred to in
> manual). In this case, *every* resulting word is splitted:
> 
> itsrm2% foo=("a b" "c d")
> itsrm2% print -l ${=foo}
> a
> b
> c
> d

The `s' flag just says where to split -- without it is done at the
well known places, with it it is done only at the string given with
the flag.

> The second question is, what is applied first - flags or modifications?
> Again, after soms tests :-)
> 
> itsrm2% foo=(ax1 bx1)
> itsrm2% print -l ${(s/x/)foo%%1*}
> a
>  b
> 
> I don't argue, that it may be predictable. Unfortunately, I simply fail to
> find the rule ...

Modification is done first. Splitting is done at the very end, in this 
case.

So the above does: apply the `%%1*', yielding the two elements `ax'
and `bx'. The `s' flag makes them be joined as usual and then broken at 
the `x's, yielding the three elements `a', ` b', and `'. Since you
didn't enclose it in quotes that last one is removed so you can't see
it. But with `"${(@s/x/)foo%%1*}" you can. And I can almost see you
trying `print -l "${(s/x/)foo%%1*}" now ;-) Perhaps surprisingly this
gives `a' and `', because without the `(@)' flag, the array elements
are first joined and re-separated at the `x's and then the `%%1*' is
applied -- which looks a bit like a bug, but then again, maybe not.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* Re: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
  1999-03-17 14:35     ` Andrej Borsenkow
@ 1999-03-17 14:52       ` Peter Stephenson
  0 siblings, 0 replies; 12+ messages in thread
From: Peter Stephenson @ 1999-03-17 14:52 UTC (permalink / raw)
  To: Peter Stephenson, zsh-workers

"Andrej Borsenkow" wrote:
> >
> > It's actually completely predictable, once you know the rule.
> >

I wrote that rather primly before I discovered the difference between
"${foo[1]}" and "${${(@)foo}[1]}" where foo is an array, which made me
rather less keen on this as a transformational generative grammar :-)

> itsrm2% foo=(axb cxd)
> itsrm2% print -l ${(s/x/)foo}
> a
> b c
> d
> 
> itsrm2% foo=("a b" "c d")
> itsrm2% print -l ${=foo}
> a
> b
> c
> d

The rule is that, before splitting, all the words are joined together; by
default this happens with a space.  (At least some of this is in the
manual, not necessarily where you want for the present purpose.)  So in
both cases the string is first joined with a space (what Chomsky would call
a trace :-) sorry, I'm enjoying myself) and the `deep structure' is
"axb cxd", "a b c d" respectively; in the second it's then split on a
space, too.  Compare

% foo=(axb cxd)
% print -l ${(j/x/s/x/)foo
a
b
c
d

where the bit you don't see is now "axbxcxd".

> The second question is, what is applied first - flags or modifications?
> Again, after soms tests :-)
> 
> itsrm2% foo=(ax1 bx1)
> itsrm2% print -l ${(s/x/)foo%%1*}
> a
>  b

Yes, that's perhaps a bit unexpected and should be documented;
${${(s/x/)foo}%%1*} does what you might have expected.  

Now I tried:

% print -l "'"${(j/x/s/x/)^foo%%1*}"'" 
'a'
''
'b'
''

where the removal of the 1 seems to happen only after the splitting, so
I'm still a bit confused.

I'll look at the manual when I get a moment, but I'm trying to remember how
to minimize some functions of matrices.

> P.S. Please, don't take me too hard. But just try to pretend itself a ZSH
> newbie for a while ...

This is useful, because people keep complaining that they don't like the
documentation, and then fail to say what's wrong with it.  This way we
finally find out.

-- 
Peter Stephenson <pws@ibmth.df.unipi.it>       Tel: +39 050 844536
WWW:  http://www.ifh.de/~pws/
Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy


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

* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
  1999-03-17 10:08   ` Peter Stephenson
@ 1999-03-17 14:35     ` Andrej Borsenkow
  1999-03-17 14:52       ` Peter Stephenson
  0 siblings, 1 reply; 12+ messages in thread
From: Andrej Borsenkow @ 1999-03-17 14:35 UTC (permalink / raw)
  To: Peter Stephenson, zsh-workers

>
> It's actually completely predictable, once you know the rule.
>

'course. What I tried to explain, that there is probably a dozen of people,
who know these rules :-( (correct me if I'm wrong)

O.K. Is it intentional?

itsrm2% foo=(axb cxd)
itsrm2% print -l ${(s/x/)foo}
a
b c
d

I won't argue, if this is correct or not. I'd just to point out
a) if this is intentional, it should be documented
b) it is very different from word splitting (which is referred to in
manual). In this case, *every* resulting word is splitted:

itsrm2% foo=("a b" "c d")
itsrm2% print -l ${=foo}
a
b
c
d

The second question is, what is applied first - flags or modifications?
Again, after soms tests :-)

itsrm2% foo=(ax1 bx1)
itsrm2% print -l ${(s/x/)foo%%1*}
a
 b

I don't argue, that it may be predictable. Unfortunately, I simply fail to
find the rule ...

cheers

/andrej

P.S. Please, don't take me too hard. But just try to pretend itself a ZSH
newbie for a while ...


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

* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-17 10:35 Sven Wischnowsky
  0 siblings, 0 replies; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-17 10:35 UTC (permalink / raw)
  To: zsh-workers


Andrej Borsenkow wrote:

> > This ounds good, but can't be done easily (I think). The problem is
> > that in the case of a `${${...}...}' the code currently just takes the
> > inner `${...}' and calls `prefork()' on it (which does most of the
> > expansions). The result is a list of strings and no other
> > information. So here, the result of an one-element array and an scalar
> > is indistinguishable. This means that we have to say in the *outer*
> > `${...}' if we want the result of the inner one to be treated as an array.
> 
> Can I formulate it as: every substitution is done as if it were the
> top-level one?

As a wish? Yes, and as I said, I'd like to have this, too.

> >
> > The problem is that this is even more uncompatible with previous
> > version than what we have now.
> >
> 
> The problem ZSH always had (and have) is very poor documentation. I think,
> the (partial) reason for it is, nobody actually knows, how it behaves. New
> features are added on ad-hoc basis, without clear picture, how the whole
> works.

This isn't a new feature, it is an attempt at making things more
consistent, more usable. Before the patches I made There was no way to 
get the inner `${...}' be treated as an array. I found this when
implementing `_long_options' where I had an expression roughly like
`${${(P)foo}[1]}'. At one point the array whose name was stored in
`foo' happened to have only one element and suddenly I got the first
character of it, not the whole element -- and there was no way to get
it. With the changed code `${(@)${(P)foo}[1]}' this works.

> Currently there are several ZSH wizards that either know all ins and outs by
> heart or know source code. It is virtually impossible for ordinary user to
> use the power ZSH provides, because the only way to do it is by trial and
> error. You never can tell, what is a result of a (mildly complicated)
> expression simply by looking at it.
> 
> Can anybody explain (in the manual) how ZSH substitution really works?
> Returning to my example:
> 
> bor@itsrm2:~%> foo=(bar baz)
> bor@itsrm2:~%> print "${(@)${foo}[1]}"
> bar baz
> bor@itsrm2:~%> print "${${(@)foo}[1]}"
> b
> 
> Could anybody explain, why? We take the value of foo, that is (bar baz). The
> whole is quoted, so it is converted to scalar. Then, all of a sudden, this
> scalar is converted back to array! Why?  What about second? On the top
> level, (@) prevents array->scalar converting:
> 
> bor@itsrm2:~%> print -l "${(@)foo}"
> bar
> baz
> 
> But why it does not happen with inner ${(@)foo} in the above case? How can I
> take array slice in double quotes?

Because (as I said in the part of my message you quoted at the top),
the outer one doesn't say that the inenr one should be treated as an
array:

  % foo=(bar baz)
  % echo "${(@)${(@)foo}[1]}"
  bar

The behavior is consistent in that in quotes you need a `(@)' in the
outer one to get the inner one split. That's all. And, as I said in a
part of the message you didn't quote I agree that this is a bit ugly
since the `(@)' has two meanings. In my example: the inner `${...}' is 
splitted into two strings due to the `(@)' in the inner expression.
Then the `(@)' in the outer expression ensures that these strings are
treated as different elements by the subscript. And finally, if we had 
a subscript selecting more than one element or no subscript at all,
the `(@)' in the outer expression would also make the result be
treated as separate strings by the `echo'.

> That is only one example of inconsistency. The answer "it is implemented
> this way" is very weak argument. What I'd like to hear - *why* is it
> implemented this way.

Because noone yet took the time to implement it differently... But
seriously: I'm pretty sure noone would object if you (or someone else) 
changes the way the inner expression is expanded as long as it does
not differ from what we have now (or before my patches) in the simple
cases. Having this cleaned up would be nice, indeed. If I were to
implement this I'd probably play with calling `paramsubst()' directly
in `multsub()' if the things starts with `${'. And then I'd have to
think a lot about and play a lot with a inner `$(...)' where we have
the problem that they can't have flags, so with them we *will* have to 
specify in the outer `${...}' what should be done with the result of
expanding it -- if we need different ways.
I'm not that unlucky with the current behavior and too busy in other
parts of the code (you may have noticed ;-), so I won't do more work
here now...

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* Re: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
  1999-03-17  9:59 ` Andrej Borsenkow
@ 1999-03-17 10:08   ` Peter Stephenson
  1999-03-17 14:35     ` Andrej Borsenkow
  0 siblings, 1 reply; 12+ messages in thread
From: Peter Stephenson @ 1999-03-17 10:08 UTC (permalink / raw)
  To: zsh-workers

"Andrej Borsenkow" wrote:
> bor@itsrm2:~%> foo=(bar baz)
> bor@itsrm2:~%> print "${(@)${foo}[1]}"
> bar baz
> bor@itsrm2:~%> print "${${(@)foo}[1]}"
> b
> 
> Could anybody explain, why?

It's actually completely predictable, once you know the rule.

In the first case the processing is
 - "${foo}" giving quoted substituion, the word "bar baz"
 - "${(@)...[1]}" where the ... is the result of the above.  This
   does array indexing on what you have already, because of the (@).
   What you have already is a single word, so that is the first word of the
   array and you get that.

In the second case, you get
 - "${(@)foo}", giving the array (bar baz)
 - "${...[1]}" on the result of that.  There is no (@), so this is
   a scalar substitution, so what we have so far is turned into a single
   word and the [1] applies to characters in that, giving the `b'.

The rule is:

  Substitution at each level only takes account of its own flags and
  whether or not it is in double quotes in deciding how to process
  what it has received from any nested substituion.  It knows whether
  or not that was an array, in case it needs to join the words or
  select one or more of them, but it has no way of knowing about nested
  flags and whether it should propagate them.

Maybe I can even invent something for the manual, if it's not going to
change.

-- 
Peter Stephenson <pws@ibmth.df.unipi.it>       Tel: +39 050 844536
WWW:  http://www.ifh.de/~pws/
Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy


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

* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
  1999-03-17  9:09 Sven Wischnowsky
@ 1999-03-17  9:59 ` Andrej Borsenkow
  1999-03-17 10:08   ` Peter Stephenson
  0 siblings, 1 reply; 12+ messages in thread
From: Andrej Borsenkow @ 1999-03-17  9:59 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

>
> This ounds good, but can't be done easily (I think). The problem is
> that in the case of a `${${...}...}' the code currently just takes the
> inner `${...}' and calls `prefork()' on it (which does most of the
> expansions). The result is a list of strings and no other
> information. So here, the result of an one-element array and an scalar
> is indistinguishable. This means that we have to say in the *outer*
> `${...}' if we want the result of the inner one to be treated as an array.
>

Can I formulate it as: every substitution is done as if it were the
top-level one?

>
> The problem is that this is even more uncompatible with previous
> version than what we have now.
>

The problem ZSH always had (and have) is very poor documentation. I think,
the (partial) reason for it is, nobody actually knows, how it behaves. New
features are added on ad-hoc basis, without clear picture, how the whole
works.

Currently there are several ZSH wizards that either know all ins and outs by
heart or know source code. It is virtually impossible for ordinary user to
use the power ZSH provides, because the only way to do it is by trial and
error. You never can tell, what is a result of a (mildly complicated)
expression simply by looking at it.

Can anybody explain (in the manual) how ZSH substitution really works?
Returning to my example:

bor@itsrm2:~%> foo=(bar baz)
bor@itsrm2:~%> print "${(@)${foo}[1]}"
bar baz
bor@itsrm2:~%> print "${${(@)foo}[1]}"
b

Could anybody explain, why? We take the value of foo, that is (bar baz). The
whole is quoted, so it is converted to scalar. Then, all of a sudden, this
scalar is converted back to array! Why?  What about second? On the top
level, (@) prevents array->scalar converting:

bor@itsrm2:~%> print -l "${(@)foo}"
bar
baz

But why it does not happen with inner ${(@)foo} in the above case? How can I
take array slice in double quotes?

That is only one example of inconsistency. The answer "it is implemented
this way" is very weak argument. What I'd like to hear - *why* is it
implemented this way.

We already had a long shot at RC_EXPAND_PARAM. Yes, it was incompatible with
previous version - but it made RC_EXPAND_PARAM finally useful - and
*predictable*. What I'd like to see in parameter expansion - it is
predictability.

cheers

/andrej




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

* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-17  9:09 Sven Wischnowsky
  1999-03-17  9:59 ` Andrej Borsenkow
  0 siblings, 1 reply; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-17  9:09 UTC (permalink / raw)
  To: zsh-workers


[The road leading to our buildin is build anew and yesterday someone
cut the cable that is our only connection to the main building. Our
system administrators say that everything is working again, although I 
haven't got all the messages from the list, yet. So this is also a test...]

Andrej Borsenkow wrote:

> > - makes the treatment of `${${...}...}' (hopefully) consistent (and
> >   this is a answer to one of Peter's questions above). The rule is:
> >   the inner `${...}' is broken into array elements if it yields more
> >   than one word and the whole thing is not quoted or if it is quoted and
> >   the `@' flag is used. I'd like to hear comments if you think that
> >   this looks and feels like the right thing.
> 
> What do you mean "one word"?

I only meant that one can't `break' *one* word into multiple `array
elements'.

> Array with single element yields one word. And
> it is very important with subscription (that behaves very funny anyway - see
> later). I prefer the case, when array yields array irrespectively of number
> of the elements.



> This is suggestion I had long ago. May be, it is the same, as you mean, but
> explicitly stated:
> 
> without qoutes
> 
>  - ${array} always gives array
>  - ${scalar} always gives scalar
>  - ${array[sub]} gives scalar
>  - ${array[sub1,sub2]} gives array (slice)
>  - ${(split)something} always gives array (may be, with single element)
>  - ${(join)something} always gives scalar
>  - $~ is considred "spliting" in this respect
> 
> in quotes
> 
>  - without (@) all yields scalar
>  - with (@) the result is array _for_the_next_level_ (for those operations,
> that yield array). The point is, the flags and subscription are applied, as
> if it were array - and the result is converted to scalar unless (@) is given
> as well.
> 
> That is, "${${(@)array}[1,3]} gives 1,2,3 elements of array as scalar. And
> "${(@)${(@)array}[1,3]}" - the same, but as three words.

This ounds good, but can't be done easily (I think). The problem is
that in the case of a `${${...}...}' the code currently just takes the 
inner `${...}' and calls `prefork()' on it (which does most of the
expansions). The result is a list of strings and no other
information. So here, the result of an one-element array and an scalar 
is indistinguishable. This means that we have to say in the *outer*
`${...}' if we want the result of the inner one to be treated as an array.

Hence these results:

> ....
> 
> bor@itsrm2:~%> foo=bar
> bor@itsrm2:~%> print ${${foo}[1]}
> bar
> 
> Sorry? Why ${foo} suddenly becomes array?
> 

1) The `${foo}' yields one word and the whole thing is not quoted, so we
get an array for it and that is then subscripted.

> bor@itsrm2:~%> print "${${foo}[1]}"
> b
> 
> With some imagination ...

2) The thing is quoted, we get a scalar and then the first char of it.

> bor@itsrm2:~%> print "${${(@)foo}[1]}"
> b
> 
> ??? Und I always believed, ${(@)foo} is array ...

3) The `(@)' has no effect because `prefork()' doesn't know about it,
gives us no information about it and since the whole thing is in
quotes, we get a scalar for the inner `${...}'.

> bor@itsrm2:~%> print "${(@)${foo}[1]}"
> bar
> 
> Poor, poor ZSH users ...

4) The `(@)' says that the `${foo}' is to be treated as an array, that is 
subscripted, and the result is broken into separate quoted words
(which you won't notice since there is only one).

Ok. Unless someone changes the code so that `multsub()' gets
information from a `paramsubst()' called via `prefork()' we are stuck
with it. But maybe we should add a new flag for the `turn the inner
<whatever> into an array', and make `(@)' work only at the outermost
level with the obvious meaning.

The problem is that this is even more uncompatible with previous
version than what we have now.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
  1999-03-15  9:46 Sven Wischnowsky
  1999-03-15 13:49 ` Peter Stephenson
@ 1999-03-16 18:07 ` Andrej Borsenkow
  1 sibling, 0 replies; 12+ messages in thread
From: Andrej Borsenkow @ 1999-03-16 18:07 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

> - makes the treatment of `${${...}...}' (hopefully) consistent (and
>   this is a answer to one of Peter's questions above). The rule is:
>   the inner `${...}' is broken into array elements if it yields more
>   than one word and the whole thing is not quoted or if it is quoted and
>   the `@' flag is used. I'd like to hear comments if you think that
>   this looks and feels like the right thing.

What do you mean "one word"? Array with single element yields one word. And
it is very important with subscription (that behaves very funny anyway - see
later). I prefer the case, when array yields array irrespectively of number
of the elements.

This is suggestion I had long ago. May be, it is the same, as you mean, but
explicitly stated:

without qoutes

 - ${array} always gives array
 - ${scalar} always gives scalar
 - ${array[sub]} gives scalar
 - ${array[sub1,sub2]} gives array (slice)
 - ${(split)something} always gives array (may be, with single element)
 - ${(join)something} always gives scalar
 - $~ is considred "spliting" in this respect

in quotes

 - without (@) all yields scalar
 - with (@) the result is array _for_the_next_level_ (for those operations,
that yield array). The point is, the flags and subscription are applied, as
if it were array - and the result is converted to scalar unless (@) is given
as well.

That is, "${${(@)array}[1,3]} gives 1,2,3 elements of array as scalar. And
"${(@)${(@)array}[1,3]}" - the same, but as three words.

Quoting does not change the fact, that innermost parameter is array or
scalar. So, in e.g. "${${(@f)array}[1,3]}", the array elements are splitted
using new lines, then three first resulting elemnts are taken and result is
scalar (single word). In "${(f)scalar}" the scalar is first splitted thus
giving array, and this array is then converted to scalar. Without quoting,
${(f)scalar} gives array. The point is, the "type" of element is propagated
to the top level. And some flags change this type.

About subscription: in ${foo[bar]} - what is "parameter expansion"? Do we
"expand" ${foo} first (using whatever flags are given) and then apply
subscription to the result - or is the whole considered as expansion? In
this case, any (...) flag should be applied _after_ subscription was taken.
This is crucial with (@) flag. I'd prefer the case, when in
"${(@)array[sub1,sub2]}" (@) aplied to the slice. That is consistent and
gives you the way to control type of the whole expression. And the type of
array is determined using rules above.

And now the really funny results (for me at least)

bor@itsrm2:~%> foo=bar
bor@itsrm2:~%> print ${${foo[1]}}
b

this is O.K.

bor@itsrm2:~%> print ${${foo}[1]}
bar

Sorry? Why ${foo} suddenly becomes array?

bor@itsrm2:~%> print "${${foo}[1]}"
b

With some imagination ...

bor@itsrm2:~%> print "${${(@)foo}[1]}"
b

??? Und I always believed, ${(@)foo} is array ...

bor@itsrm2:~%> print "${(@)${foo}[1]}"
bar

Poor, poor ZSH users ...

cheers

/andrej


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

* Re: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
  1999-03-15  9:46 Sven Wischnowsky
@ 1999-03-15 13:49 ` Peter Stephenson
  1999-03-16 18:07 ` Andrej Borsenkow
  1 sibling, 0 replies; 12+ messages in thread
From: Peter Stephenson @ 1999-03-15 13:49 UTC (permalink / raw)
  To: zsh-workers

Sven Wischnowsky wrote:
> > This wasn't working for me.  The following version is.  Do I really need
> > all those (@)?  I was too lazy to experiment.  In fact, why do I need the
> > double quotes in this case?  There's no harm here in eliding empty
> > elements.
> 
> In this case (and some others in the example functions) we almost
> certainly don't need the double quotes (and hence no `(@)'), this is
> just a habit of mine...

(The substitution in question was
  "${(@)${(@)${(@f)$(set)}%%\=*}:gs/'//}"
to get the names of set parameters.)

The problem in this case is the $(set), which needs to be split line by
line rather than on any whitespace.  If I've understood what's going on
correctly, the only way of doing that, even with the (f) flag, is in double
quotes.  The (f) has an effect outside quotes, but since a $(...) there
produces the whole thing on one line, it's not what you want --- you get
everything in a single argument.  I haven't found a way round.

> - makes the treatment of `${${...}...}' (hopefully) consistent (and
>   this is a answer to one of Peter's questions above). The rule is:
>   the inner `${...}' is broken into array elements if it yields more
>   than one word and the whole thing is not quoted or if it is quoted and
>   the `@' flag is used. I'd like to hear comments if you think that
>   this looks and feels like the right thing.

It sounds right, although it's possible there are cases which make it more
complicated in practice.

> - allows the `${#:-foo}' Peter found. I think there is no harm in
>   allowing it.

In this case, I can't see any problem, since before it was only a rather
roundabout way of getting the same as $#, as far as I can see.  Maybe if
you stuck to the rules it would return the length of `foo' if $argv was
empty, otherwise $#, but that's not exactly useful.  Ksh rejects this
syntax completely.

>   The behavior is a bit weird, though, because `${foo-bar}' uses
>   `multsub', too. I haven't changed the call to it, yet, so the result 
>   is that the `bar' is broken into an array -- always. This means that 
>   `${#:-$foo}' will yield `1' for strings and the number of elements
>   if `bar' is `$baz' where `baz' is an array. I didn't change it
>   because I wanted to ask what it should do first, suggestions are:
> 
>   1) let it treat the `bar' always as a string (i.e. let it never be
>      split into array elements); I guess this is what most people
>      would expect (and in the manual the thing is called `word')

Since (without shwordsplit)

  % args() { print $#; }
  % args ${foo:-foo bar}
  1

this is the natural thing to do.

>   2) like 1), but if combined with the `A' flag, let it be treated as
>      an array

Some extension like this is reasonable, but the obvious candidate is
${(w)#:-foo bar}, which is supposed to have exactly this effect on $# for a
string.

 % foo="foo bar"
 % print ${(w)#foo}
 2

-- 
Peter Stephenson <pws@ibmth.df.unipi.it>       Tel: +39 050 844536
WWW:  http://www.ifh.de/~pws/
Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy


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

* PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-15  9:46 Sven Wischnowsky
  1999-03-15 13:49 ` Peter Stephenson
  1999-03-16 18:07 ` Andrej Borsenkow
  0 siblings, 2 replies; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-15  9:46 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> This wasn't working for me.  The following version is.  Do I really need
> all those (@)?  I was too lazy to experiment.  In fact, why do I need the
> double quotes in this case?  There's no harm here in eliding empty
> elements.

In this case (and some others in the example functions) we almost
certainly don't need the double quotes (and hence no `(@)'), this is
just a habit of mine...

Over the weekend I had prepared the patch below, which

- improves the parsing of a subscript on the left hand side of an
  parameter assignment. Previously somthing like `a[${i%%\=*}]=foo'
  didn't work because the (very simple) parsing done found the `='
  inside the brackets and then tried to use that to separate the two
  sides of the assignment. For array-assignments it worked.
  The hunk in `compinit' makes use of this -- that's the place where I 
  discovered it.
- makes the treatment of `${${...}...}' (hopefully) consistent (and
  this is a answer to one of Peter's questions above). The rule is:
  the inner `${...}' is broken into array elements if it yields more
  than one word and the whole thing is not quoted or if it is quoted and
  the `@' flag is used. I'd like to hear comments if you think that
  this looks and feels like the right thing.
- allows the `${#:-foo}' Peter found. I think there is no harm in
  allowing it.
  The behavior is a bit weird, though, because `${foo-bar}' uses
  `multsub', too. I haven't changed the call to it, yet, so the result 
  is that the `bar' is broken into an array -- always. This means that 
  `${#:-$foo}' will yield `1' for strings and the number of elements
  if `bar' is `$baz' where `baz' is an array. I didn't change it
  because I wanted to ask what it should do first, suggestions are:

  1) let it treat the `bar' always as a string (i.e. let it never be
     split into array elements); I guess this is what most people
     would expect (and in the manual the thing is called `word')
  2) like 1), but if combined with the `A' flag, let it be treated as
     an array
  3) do the same as for `${${...}...}', i.e., treat it as an array
     unless the whole thing is quoted (or quoted and with the `@')
     flag

  Note that none of these will change the behavior of things that
  worked before, the difference appears only if it is combined with `#'.

Bye
 Sven

diff -u os/parse.c Src/parse.c
--- os/parse.c	Fri Mar 12 20:47:16 1999
+++ Src/parse.c	Fri Mar 12 21:31:35 1999
@@ -955,9 +955,17 @@
 	    nocorrect = 1;
 	else if (tok == ENVSTRING) {
 	    struct varasg *v = (struct varasg *)make_varnode();
+	    char *p;
 
 	    v->type = PM_SCALAR;
-	    equalsplit(v->name = tokstr, &v->str);
+	    v->name = tokstr;
+	    for (p = tokstr; *p && *p != Inbrack && *p != '='; p++);
+	    if (*p == Inbrack && !skipparens(Inbrack, Outbrack, &p) &&
+		*p == '=') {
+		*p = '\0';
+		v->str = p + 1;
+	    } else
+		equalsplit(tokstr, &v->str);
 	    addlinknode(c->vars, v);
 	    isnull = 0;
 	} else if (tok == ENVARRAY) {
diff -u os/subst.c Src/subst.c
--- os/subst.c	Fri Mar 12 20:47:16 1999
+++ Src/subst.c	Fri Mar 12 21:16:49 1999
@@ -941,6 +941,7 @@
 	} else if ((*s == '#' || *s == Pound) &&
 		   (iident(s[1])
 		    || s[1] == '*' || s[1] == Star || s[1] == '@'
+		    || s[1] == '-' || (s[1] == ':' && s[2] == '-')
 		    || (isstring(s[1]) && (s[2] == Inbrace || s[2] == Inpar))))
 	    getlen = 1 + whichlen, s++;
 	else if (*s == '~' || *s == Tilde) {
@@ -976,7 +977,7 @@
 	skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
 	sav = *s;
 	*s = 0;
-	if (multsub(&val, (((quoted || aspar) && !nojoin) ? NULL : &aval),
+	if (multsub(&val, ((!aspar && (!quoted || nojoin)) ? &aval : NULL),
 		    &isarr, NULL) &&
 	    quoted) {
 	    isarr = -1;
diff -u oc/Core/compinit Completion/Core/compinit
--- oc/Core/compinit	Fri Mar 12 20:40:19 1999
+++ Completion/Core/compinit	Fri Mar 12 21:33:23 1999
@@ -221,12 +221,11 @@
 # set key `baz' to the empty string.
 
 compconf() {
-  local i name
+  local i
 
   for i; do
     if [[ "$i" = *\=* ]]; then
-      name="${i%%\=*}"
-      compconfig[$name]="${i#*\=}"
+      compconfig[${i%%\=*}]="${i#*\=}"
     else
       compconfig[$i]=''
     fi

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

end of thread, other threads:[~1999-03-25 12:03 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-03-16 11:50 PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter Sven Wischnowsky
1999-03-25 12:00 ` ${...:-...} again and subst clarification E: " Andrej Borsenkow
  -- strict thread matches above, loose matches on Subject: below --
1999-03-17 14:59 Sven Wischnowsky
1999-03-17 10:35 Sven Wischnowsky
1999-03-17  9:09 Sven Wischnowsky
1999-03-17  9:59 ` Andrej Borsenkow
1999-03-17 10:08   ` Peter Stephenson
1999-03-17 14:35     ` Andrej Borsenkow
1999-03-17 14:52       ` Peter Stephenson
1999-03-15  9:46 Sven Wischnowsky
1999-03-15 13:49 ` Peter Stephenson
1999-03-16 18:07 ` Andrej Borsenkow

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).