Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: for loop 'bad math expression'



On Sun, Feb 4, 2024, at 10:51 AM, Ray Andrews wrote:
> That astonishes me.  I've never heard of any such thing.  Nobody
> tells you these things.

I'm not sure if the zsh manual spells this behavior out explicitly,
but bash and ksh share it.


> # abc was a string, now it's the name of an integer:

These are not mutually exclusive.  The value of var remains "abc"
and does not change at any point.  The important thing is that it
is *interpreted* a certain way *in arithmetic contexts*.


> % let abc+=3; print -- $((var))
> 3

This result does not correlate with the commands you've actually
shown here.

	% var=abc
	% abc=1
	% let abc+=3
	% print -- $((var))
	4


> # var still wants to be scalar:
> % var+=3; print -- $var 
> abc3

It doesn't "want" to be scalar, it IS scalar.  But that's irrelevant.
What's relevant is that it does not have the integer attribute, so
"var+=3" performs string concatenation and not arithmetic incrementing.
You'd see the same thing with "abc", even though it looks like a
number.

	% abc=1
	% abc+=3
	% typeset -p abc
	typeset abc=13

(I don't know why all of a sudden you've switched from using "let"
to not using it.)


> # So once var has been touched directly the link to abc is broken:
> % abc+=2; print -- $((var))
> 0
>
> % abc=2; print -- $((var))
> 0

It's not about "touching", and there is no "link".  You CHANGED its
value to "abc3", and there is no such variable, so its arithmetic
value is recursively taken to be zero.


> ... I suppose there's a good reason for it, but that leaves me dumbfounded.

If you were given these algebraic equations and asked what the value
of "c" is, presumably you'd say "one" and not "the letter 'b'".

	a = 1
	b = a
	c = b

Same thing in shell arithmetic.

	% a=1
	% b=a
	% c=b
	% print -- $((c))
	1


> % Sonnet_1='From_fairest_flowers_we_desire_increase'; print -- $Sonnet_1
> From_fairest_flowers_we_desire_increase

There is no arithmetic context here, so you just get the raw value.


> % From_fairest_flowers_we_desire_increase=1        
>
> % print -- $((Sonnet_1))
> 1
>
> ... ok ...

There *is* an arithmetic context here, so it's interpreted as an
arithmetic expression.  What is confusing about this?  You're
intentionally using unwieldy names, but the principle is the same
as if you'd just used "a" and "b".


> Anyway, the lesson is just not to assign a glob expansion to an
> integer.

The real lesson might be that you should avoid the integer attribute
until you understand shell arithmetic better.


-- 
vq




Messages sorted by: Reverse Date, Date, Thread, Author