* for loop 'bad math expression' @ 2024-01-30 3:39 Ray Andrews 2024-01-30 3:46 ` Ray Andrews 0 siblings, 1 reply; 25+ messages in thread From: Ray Andrews @ 2024-01-30 3:39 UTC (permalink / raw) To: Zsh Users Been reviewing and deleting old email backups but saving some: for bb in *.eml~save*; do # Error msg. points to this line. thunderbird -file $bb echo "\nFile: $bb: Press 's' to save, 'd' to delete or '^C' to quit." read -sk1 key case $key in d ) rm -v $bb ;; s ) mv -v $bb save-$bb ;; # Rename so not viewed again. * ) errormsg "skipping file ..." ;; esac done ... it's been working fine, done thousands. But just now it threw me an error: global:20: bad math expression: operator expected at `CDF8.eml' .... there's no such file. They all have eight characters then '.eml': 607 [2013-01-16--18:57] 48EE0E21.eml* 694 [2013-01-16--18:57] 48ECE166.eml* 10115 [2013-01-16--18:57] 48E4BB08.eml* ... like that. And if saved: 2842 [2013-01-16--18:57] save-48137E34.eml* 3135 [2013-01-16--18:57] save-4812320B.eml* 2278 [2013-01-16--18:57] save-48122AEC.eml* Does anyone have the slightest clue what's going on here? ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-01-30 3:39 for loop 'bad math expression' Ray Andrews @ 2024-01-30 3:46 ` Ray Andrews 2024-01-30 4:04 ` Bart Schaefer 0 siblings, 1 reply; 25+ messages in thread From: Ray Andrews @ 2024-01-30 3:46 UTC (permalink / raw) To: zsh-users On 2024-01-29 19:39, Ray Andrews wrote: > > > Does anyone have the slightest clue what's going on here? > > BTW here's a hint: with 'set -x' I see this: +global:20:for for>bb=48E3CDF8.eml global:20: bad math expression: operator expected at `CDF8.eml' ... so somehow it's taking that filename and cutting it down and turning it into a math expression. The file exists and is perfectly normal, ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-01-30 3:46 ` Ray Andrews @ 2024-01-30 4:04 ` Bart Schaefer 2024-01-30 4:06 ` Bart Schaefer 0 siblings, 1 reply; 25+ messages in thread From: Bart Schaefer @ 2024-01-30 4:04 UTC (permalink / raw) To: Ray Andrews; +Cc: zsh-users On Mon, Jan 29, 2024 at 7:47 PM Ray Andrews <rayandrews@eastlink.ca> wrote: > > +global:20:for for>bb=48E3CDF8.eml > global:20: bad math expression: operator expected at `CDF8.eml' % x=48E3CDF8 % echo $x 48E3CDF8 % integer x zsh: bad math expression: operator expected at `CDF8' So, something has declared "bb" to be an integer. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-01-30 4:04 ` Bart Schaefer @ 2024-01-30 4:06 ` Bart Schaefer 2024-01-30 4:17 ` Ray Andrews 0 siblings, 1 reply; 25+ messages in thread From: Bart Schaefer @ 2024-01-30 4:06 UTC (permalink / raw) To: Ray Andrews; +Cc: zsh-users On Mon, Jan 29, 2024 at 8:04 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > So, something has declared "bb" to be an integer. Or a float, or some other numeric type, they all produce that error. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-01-30 4:06 ` Bart Schaefer @ 2024-01-30 4:17 ` Ray Andrews 2024-01-30 13:44 ` Ray Andrews 0 siblings, 1 reply; 25+ messages in thread From: Ray Andrews @ 2024-01-30 4:17 UTC (permalink / raw) To: zsh-users On 2024-01-29 20:06, Bart Schaefer wrote: > On Mon, Jan 29, 2024 at 8:04 PM Bart Schaefer <schaefer@brasslantern.com> wrote: >> So, something has declared "bb" to be an integer. > Or a float, or some other numeric type, they all produce that error. Right you are. Yeah, some careless use of the variable, I didn't bother to declare it local so it's some stray coming from somewhere else. I hate that. Orphaned variables hanging around waiting to get into trouble. I'll track down the leak. Thank you Sensei. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-01-30 4:17 ` Ray Andrews @ 2024-01-30 13:44 ` Ray Andrews 2024-01-30 14:30 ` Lawrence Velázquez 2024-02-03 23:52 ` Bart Schaefer 0 siblings, 2 replies; 25+ messages in thread From: Ray Andrews @ 2024-01-30 13:44 UTC (permalink / raw) To: zsh-users On 2024-01-29 20:17, Ray Andrews wrote: > > On 2024-01-29 20:06, Bart Schaefer wrote: >> On Mon, Jan 29, 2024 at 8:04 PM Bart Schaefer >> <schaefer@brasslantern.com> wrote: >>> So, something has declared "bb" to be an integer. >> Or a float, or some other numeric type, they all produce that error. > > Right you are. Yeah, some careless use of the variable, I didn't > bother to declare it local so it's some stray coming from somewhere > else. I hate that. Orphaned variables hanging around waiting to get > into trouble. I'll track down the leak. Thank you Sensei. BTW Bart, just a post mortem on that: I know there are situations where a plain vanilla scalar is promoted to integer when the situation requires it. In the above, I wonder about an automatic demotion. The situation plainly had nothing to do with arithmetic OTOH perhaps there could be situations where a for loop like that one really would be doing arithmetic there in which case type assumptions would be unwise. OTOOH perhaps automatic 'non demotion' would be possible -- zsh might have robust defenses against making a mistake. Dunno, but as dangerous as 'obvious' can be, it seems to me that a glob expansion of a bunch of filenames is obviously nothing to do with arithmetic. 3 /aWorking/Zsh/Source/Wk 0 % var=abc; var=$(( 1+1 )); echo $var 2 for bb in *.eml~save*; do ... just as var can be automatically turned into an integer so to perhaps bb could be clearly understood to be scalar in that situation. Again, unless I really might have intended something mathematical there which is hard to imagine. > > > ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-01-30 13:44 ` Ray Andrews @ 2024-01-30 14:30 ` Lawrence Velázquez 2024-02-03 23:52 ` Bart Schaefer 1 sibling, 0 replies; 25+ messages in thread From: Lawrence Velázquez @ 2024-01-30 14:30 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 878 bytes --] > On Jan 30, 2024, at 8:50 AM, Ray Andrews <rayandrews@eastlink.ca> wrote: > > BTW Bart, just a post mortem on that: I know there are situations where a plain vanilla scalar is promoted to integer when the situation requires it. In what situations is the integer attribute automatically given to an existing variable that did not previously have it? > In the above, I wonder about an automatic demotion. The situation plainly had nothing to do with arithmetic Under no circumstances should zsh take it upon itself to automatically remove the integer attribute. If you don’t want it to enforce the integer constraint, don’t assign the attribute. Nothing requires you to use it. > OTOOH perhaps automatic 'non demotion' would be possible -- zsh might have robust defenses against making a mistake. This is wishful thinking. -- vq Sent from my iPhone [-- Attachment #2: Type: text/html, Size: 1935 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-01-30 13:44 ` Ray Andrews 2024-01-30 14:30 ` Lawrence Velázquez @ 2024-02-03 23:52 ` Bart Schaefer 2024-02-04 1:14 ` Ray Andrews 1 sibling, 1 reply; 25+ messages in thread From: Bart Schaefer @ 2024-02-03 23:52 UTC (permalink / raw) To: zsh-users On Tue, Jan 30, 2024 at 5:44 AM Ray Andrews <rayandrews@eastlink.ca> wrote: > > BTW Bart, just a post mortem on that: I know there are situations where > a plain vanilla scalar is promoted to integer As Lawrence also suggested, I don't believe that happens. If a parameter is created inside a math expression it will be assigned an appropriate numeric type, but the type of an existing scalar is not changed. Note "created" here includes the case where the parameter was declared but later unset and then assigned again in math context. Parameters may also be converted to and from arrays by assignment, and that includes converting from an array to a numeric type when assigned in math context. Maybe that's what you're thinking of. > I wonder about an automatic demotion. The > situation plainly had nothing to do with arithmetic Context-awareness doesn't extend that far. Globbing is already done and gone by the time "for" assigns its loop variable, nothing tells "for" where the loop values came from, and shell words on a command line carry no type information. > perhaps automatic 'non demotion' would be possible -- zsh might have > robust defenses against making a mistake. You might try setopt warn_create_global to detect cases of names "leaking". ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-03 23:52 ` Bart Schaefer @ 2024-02-04 1:14 ` Ray Andrews 2024-02-04 2:05 ` Lawrence Velázquez 2024-02-04 14:43 ` Mark J. Reed 0 siblings, 2 replies; 25+ messages in thread From: Ray Andrews @ 2024-02-04 1:14 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 1578 bytes --] On 2024-02-03 15:52, Bart Schaefer wrote: > As Lawrence also suggested, I don't believe that happens. If a > parameter is created inside a math expression it will be assigned an > appropriate numeric type, but the type of an existing scalar is not > changed. 0 /usr/share/info 0 % var=abc; let var+=2; echo $var 2 ... it looks like the shell is simply throwing away 'abc' and starting afresh with an integer and then incrementing it. And in the manual: Note that assignment may implicitly change the attributes of a parameter. For example, assigning a number to a variable in arithmetic evaluation may change its type to integer or float, and with GLOB_ASSIGN assigning a pattern to a variable may change its type to an array. > Context-awareness doesn't extend that far. Globbing is already done > and gone by the time "for" assigns its loop variable, nothing tells > "for" where the loop values came from, and shell words on a command > line carry no type information. Sure. I'm hardly surprised it wouldn't be practical, it was the most speculative sort of question. And there really is no foul since my variable shouldn't have been an integer. Actually, philosophically I'm opposed to most hand-holding anyway. With experience I'd probably instantly detect what was going on there. But when you first bump into it, it seems inexplicable. > > You might try setopt warn_create_global to detect cases of names "leaking". > Never played with that. Sounds useful. As always my 'C-brain' tells me that indiscipline with variables is intolerable. [-- Attachment #2: Type: text/html, Size: 2599 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 1:14 ` Ray Andrews @ 2024-02-04 2:05 ` Lawrence Velázquez 2024-02-04 4:20 ` Bart Schaefer 2024-02-04 15:51 ` Ray Andrews 2024-02-04 14:43 ` Mark J. Reed 1 sibling, 2 replies; 25+ messages in thread From: Lawrence Velázquez @ 2024-02-04 2:05 UTC (permalink / raw) To: zsh-users On Sat, Feb 3, 2024, at 8:14 PM, Ray Andrews wrote: > On 2024-02-03 15:52, Bart Schaefer wrote: >> As Lawrence also suggested, I don't believe that happens. If a >> parameter is created inside a math expression it will be assigned an >> appropriate numeric type, but the type of an existing scalar is not >> changed. > 0 /usr/share/info 0 % var=abc; let var+=2; echo $var > > 2 > ... it looks like the shell is simply throwing away 'abc' and starting > afresh with an integer and then incrementing it. No, that's not what happens. Within arithmetic expressions, the contents of variables undergo recursive arithmetic evaluation, so the value of "var", "abc", is interpreted as another variable name, which is itself evaluated. Since there is no "abc" variable, its arithmetic value is taken to be zero, so the result is 0 + 2 = 2. (The result would be the same if "abc" were set to an empty value.) A less trivial example should make this clearer: % var=abc % unset abc % print -- $((var)) 0 % abc=1 % print -- $((var)) 1 % abc=1+1 % typeset -p abc typeset abc=1+1 % print -- $((var)) 2 % abc='1.0 * PPID / SECONDS - RANDOM' % typeset -p abc typeset abc='1.0 * PPID / SECONDS - RANDOM' % print -- $((var)) -10080.313725490196 -- vq ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 2:05 ` Lawrence Velázquez @ 2024-02-04 4:20 ` Bart Schaefer 2024-02-04 16:08 ` Ray Andrews 2024-02-04 15:51 ` Ray Andrews 1 sibling, 1 reply; 25+ messages in thread From: Bart Schaefer @ 2024-02-04 4:20 UTC (permalink / raw) To: zsh-users On Sat, Feb 3, 2024 at 6:06 PM Lawrence Velázquez <larryv@zsh.org> wrote: > > On Sat, Feb 3, 2024, at 8:14 PM, Ray Andrews wrote: > > 0 /usr/share/info 0 % var=abc; let var+=2; echo $var > > > > 2 > > ... it looks like the shell is simply throwing away 'abc' and starting > > afresh with an integer and then incrementing it. > > No, that's not what happens. Within arithmetic expressions, the > contents of variables undergo recursive arithmetic evaluation This has been a very thorough description of the arithmetic process in zsh, but I think misses one important detail: % var=abc % typeset -p var typeset var=abc % let var+=2 % typeset -p var typeset var=2 Note that var has NOT acquired the "-i" (integer) attribute, despite having been assigned a number value. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 4:20 ` Bart Schaefer @ 2024-02-04 16:08 ` Ray Andrews 2024-02-04 20:56 ` Lawrence Velázquez 0 siblings, 1 reply; 25+ messages in thread From: Ray Andrews @ 2024-02-04 16:08 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 709 bytes --] On 2024-02-03 20:20, Bart Schaefer wrote: > Note that var has NOT acquired the "-i" (integer) attribute, despite > having been assigned a number value. I noticed that myself. I expect that all this goes back to ancient history -- arithmetic would have been an add-on at some point and integers were never robustly typed, just scalars subject to special processing, so ' $(( )) ' says: "treat me mathematically, even tho I'm otherwise just a scalar". But in my previous post it would seem that 'abc' IS an integer because it increments like one, but even then typeset -p shows it as scalar. It starts as a string assigned to 'var' but it would seem it gets 'promoted' to an integer variable. > [-- Attachment #2: Type: text/html, Size: 1365 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 16:08 ` Ray Andrews @ 2024-02-04 20:56 ` Lawrence Velázquez 0 siblings, 0 replies; 25+ messages in thread From: Lawrence Velázquez @ 2024-02-04 20:56 UTC (permalink / raw) To: zsh-users On Sun, Feb 4, 2024, at 11:08 AM, Ray Andrews wrote: > But in my previous post it would seem that 'abc' IS an integer because it increments like one, but even then typeset -p shows it as scalar. No. It "increments like one" because you ran "abc=1; let abc+=3", and the arguments to "let" are interpreted as arithmetic expressions. If you'd run "abc=1; abc+=3" you would have gotten string concatenation. > It starts as a string assigned to 'var' but it would seem it gets 'promoted' to an integer variable. What? When you ran "abc=1" *you* created that variable. And it's not "an integer variable"; it doesn't have the integer attribute. -- vq ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 2:05 ` Lawrence Velázquez 2024-02-04 4:20 ` Bart Schaefer @ 2024-02-04 15:51 ` Ray Andrews 2024-02-04 20:48 ` Lawrence Velázquez 1 sibling, 1 reply; 25+ messages in thread From: Ray Andrews @ 2024-02-04 15:51 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 1227 bytes --] On 2024-02-03 18:05, Lawrence Velázquez wrote: > % var=abc > > % unset abc > % print -- $((var)) > 0 > > % abc=1 > % print -- $((var)) > 1 > > % abc=1+1 > % typeset -p abc > typeset abc=1+1 > % print -- $((var)) > 2 > > % abc='1.0 * PPID / SECONDS - RANDOM' > % typeset -p abc > typeset abc='1.0 * PPID / SECONDS - RANDOM' > % print -- $((var)) > -10080.313725490196 > That astonishes me. I've never heard of any such thing. Nobody tells you these things. % var=abc; print -- $var abc % abc=1; print -- $((var)) 1 # abc was a string, now it's the name of an integer: % let abc+=3; print -- $((var)) 3 # var still wants to be scalar: % var+=3; print -- $var abc3 # So once var has been touched directly the link to abc is broken: % abc+=2; print -- $((var)) 0 % abc=2; print -- $((var)) 0 ... I suppose there's a good reason for it, but that leaves me dumbfounded. % Sonnet_1='From_fairest_flowers_we_desire_increase'; print -- $Sonnet_1 From_fairest_flowers_we_desire_increase % From_fairest_flowers_we_desire_increase=1 % print -- $((Sonnet_1)) 1 ... ok ... Anyway, the lesson is just not to assign a glob expansion to an integer. Never, ever. Sorry for the trouble gentlemen. [-- Attachment #2: Type: text/html, Size: 2000 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 15:51 ` Ray Andrews @ 2024-02-04 20:48 ` Lawrence Velázquez 2024-02-04 21:09 ` Bart Schaefer 2024-02-05 2:10 ` Bart Schaefer 0 siblings, 2 replies; 25+ messages in thread From: Lawrence Velázquez @ 2024-02-04 20:48 UTC (permalink / raw) To: zsh-users 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 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 20:48 ` Lawrence Velázquez @ 2024-02-04 21:09 ` Bart Schaefer 2024-02-04 21:23 ` Bart Schaefer 2024-02-05 2:10 ` Bart Schaefer 1 sibling, 1 reply; 25+ messages in thread From: Bart Schaefer @ 2024-02-04 21:09 UTC (permalink / raw) To: zsh-users On Sun, Feb 4, 2024 at 12:49 PM Lawrence Velázquez <larryv@zsh.org> wrote: > > (I don't know why all of a sudden you've switched from using "let" > to not using it.) I believe he's expecting assignments to work the same way on "numbers" whether or not they are declared as integers. This goes back to expecting arithmetic to promote strings to integers. For the rest of the audience ... Using % let var=value always applies math context, just as ((...)) and $((...)) and $[...] do. Bare assignments % var=value apply math context only when "var" already has a numeric type. Otherwise, the more usual case, it's string assignment (ignoring arrays here). Using typeset, declare, or local applies math context when an integer option (-i, -F, etc.) is provided OR when var already has a numeric type. > > ... I suppose there's a good reason for it, but that leaves me dumbfounded. Historically, I expect this results from lack in the base "sh" of user-defined math functions. That is, you can write func="a+b*c" let a=2 b=3 c=5 print $((func)) to get 17. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 21:09 ` Bart Schaefer @ 2024-02-04 21:23 ` Bart Schaefer 0 siblings, 0 replies; 25+ messages in thread From: Bart Schaefer @ 2024-02-04 21:23 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 272 bytes --] On Sun, Feb 4, 2024 at 1:09 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > Historically, I expect this results from lack in the base "sh" of > user-defined math functions. > Also perhaps to replicate the behavior of /bin/expr, though that's iffy-er. [-- Attachment #2: Type: text/html, Size: 572 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 20:48 ` Lawrence Velázquez 2024-02-04 21:09 ` Bart Schaefer @ 2024-02-05 2:10 ` Bart Schaefer 2024-02-05 2:43 ` Mikael Magnusson 2024-02-05 15:21 ` Ray Andrews 1 sibling, 2 replies; 25+ messages in thread From: Bart Schaefer @ 2024-02-05 2:10 UTC (permalink / raw) To: zsh-users On Sun, Feb 4, 2024 at 12:49 PM Lawrence Velázquez <larryv@zsh.org> wrote: > > I'm not sure if the zsh manual spells this behavior out explicitly, > but bash and ksh share it. "Arithmetic Evaluation" says (pretty far down after the discussion of operators): === Named parameters and subscripted arrays can be referenced by name within an arithmetic expression without using the parameter expansion syntax. For example, ((val2 = val1 * 2)) assigns twice the value of $val1 to the parameter named val2. =(and later)= Scalar variables can hold integer or floating point values at different times; there is no memory of the numeric type in this case. If a variable is first assigned in a numeric context without previously being declared, it will be implicitly typed as integer or float and retain that type either until the type is explicitly changed or until the end of the scope. This can have unforeseen consequences. === It doesn't explicitly say how "the value of $val1" is determined, but if it were expanded with $val1 you'd get the whole text string which would then be interpreted as arithmetic, so expanding without the $ works the same. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-05 2:10 ` Bart Schaefer @ 2024-02-05 2:43 ` Mikael Magnusson 2024-02-05 2:50 ` Bart Schaefer 2024-02-05 15:21 ` Ray Andrews 1 sibling, 1 reply; 25+ messages in thread From: Mikael Magnusson @ 2024-02-05 2:43 UTC (permalink / raw) To: Bart Schaefer; +Cc: zsh-users On 2/5/24, Bart Schaefer <schaefer@brasslantern.com> wrote: > On Sun, Feb 4, 2024 at 12:49 PM Lawrence Velázquez <larryv@zsh.org> wrote: >> >> I'm not sure if the zsh manual spells this behavior out explicitly, >> but bash and ksh share it. > > "Arithmetic Evaluation" says (pretty far down after the discussion of > operators): > === > Named parameters and subscripted arrays can be referenced by name within > an arithmetic expression without using the parameter expansion syntax. > For example, > ((val2 = val1 * 2)) > assigns twice the value of $val1 to the parameter named val2. > > =(and later)= > > Scalar variables can hold integer or floating point values at different > times; there is no memory of the numeric type in this case. > > If a variable is first assigned in a numeric context without previously > being declared, it will be implicitly typed as integer or float and > retain that type either until the type is explicitly changed or until > the end of the scope. This can have unforeseen consequences. > === > > It doesn't explicitly say how "the value of $val1" is determined, but > if it were expanded with $val1 you'd get the whole text string which > would then be interpreted as arithmetic, so expanding without the $ > works the same. This last bit is not 100% true, a parameter will combine into its context with $ but not without: % a=3+2 % echo $(( 5 / a )) # 5/5 1 % echo $(( 5 / $a )) # 5/3 + 2 3 I think effectively you can think of foo as ($foo), at least in all cases I can think of to try. -- Mikael Magnusson ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-05 2:43 ` Mikael Magnusson @ 2024-02-05 2:50 ` Bart Schaefer 0 siblings, 0 replies; 25+ messages in thread From: Bart Schaefer @ 2024-02-05 2:50 UTC (permalink / raw) To: zsh-users On Sun, Feb 4, 2024 at 6:43 PM Mikael Magnusson <mikachu@gmail.com> wrote: > > I think effectively you can think of foo as ($foo), at least in all > cases I can think of to try. Excellent point. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-05 2:10 ` Bart Schaefer 2024-02-05 2:43 ` Mikael Magnusson @ 2024-02-05 15:21 ` Ray Andrews 2024-02-05 15:48 ` Mark J. Reed 1 sibling, 1 reply; 25+ messages in thread From: Ray Andrews @ 2024-02-05 15:21 UTC (permalink / raw) To: zsh-users Gentlemen: I'm a bit behind here. I hadn't expected this to thread to get so involved. We may have a bit of a mishmash here, thanks for your patience as I try to sort it out: > Did you see my followup? The variable does not get "promoted"; it's still a string, as you can tell by the fact that += appends to it instead of adding. Right, 'var' isn't fiddled with. It just seem that taking the value of var and using it as the name of a brand new variable seems a bit strange to me. Who cares? Even I don't care, all that matters is that I'm aware of the situation. I don't like German grammar either but the Germans don't care. At this point all that remains 'open' is that I think 'abc' should 'typedef -p' as an integer. And it seems, as I said, that any direct assignment to 'var' breaks the relationship with 'abc'. > When I wrote "x+=d", it was not inside arithmetic context, so the shell did not interpret either x or d as a number; it just appended the literal value "d" onto the end of the string held in x. Right. My own post included a demonstration of that. I get it. Dunno, maybe the shell's internal machinery requires the creation of 'abc' as a new variable in order to perform the arithmetic. ... Come to think of it, that makes sense. I'd just not expect the new variable to be visible but that's a trivial matter. % var="abc+def" % abc=2 % def=3 % echo $(( var )) 5 ... that stretches my mind yet again. Interesting that 'var' is completely passive as to what "abc+def" might possibly mean until such times as an answer is demanded by the echo. % var="abc+def"; echo $var abc+def ... what must be a simple string when written becomes an addition of two variables retroactively. Ok ... if that's the way it is then that's the way it is. Yeah ... within the $(()) the string 'abc+def' NOW becomes an addition of two variables. Sure ... interpreted ... not C ... not retroactive either. more like indeterminate. > and this interpretation came about quite naturally from some incremental improvements in the shell's ability to do arithmetic. Right, as I said, arithmetic would have accreted onto the shell at some point, so had to be merged in with existing data types. Sorta like an associative array is 'really' just a normal array under the hood, but given a different interpretation. Thus the way an A array is easy to break if you aren't careful. > See, the shell has never really had data types like other programming languages. Exactly. But it takes deep surgery to cut the C-think out of the brain. "abc+def" looks like a string is a string is a string. > ... BASIC got the name from the way you introduce names for things in a math proof or paper. The depth of your historical knowledge astonishes me Mark. >Ok, not quite shut up yet. One note: % z=`expr $x + $y` ... actually it's these tortures that are exactly the sort of therapy I need. Too bad there wasn't some document: "Shell programing for folks who are used to strongly typed languages." > No. It "increments like one" because you ran "abc=1; let abc+=3", and the arguments to "let" are interpreted as arithmetic expressions. If you'd run "abc=1; abc+=3" you would have gotten string concatenation. RIGHT! Got it. > Using > % let var=value > always applies math context, just as ((...)) and $((...)) and $[...] do. ... it's another gotcha ... I know and expect that $((()) has its internal grammar. But 'let' seems ... naked ... for lack of a better word and it's a strain on grammatical rigor that it gets special, invisible favors. Don't like it. But it's one of those ancient traditions that's written in stone, I take it. > All your examples have been broken, and your conjectures confused. Yes. One tries to form an inner model of what's going on. Seems there's no Phlogiston after all ;-) > ... This can have unforeseen consequences. HA! Yes, that's a little bit of comfort for poor wretches like myself. Like trying to get somewhere in Mexico City traffic, one simply needs to be very careful. I expect if we had history to do over again, shells would have proper typing and all of this would be 10X simpler. Thanks guys. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-05 15:21 ` Ray Andrews @ 2024-02-05 15:48 ` Mark J. Reed 0 siblings, 0 replies; 25+ messages in thread From: Mark J. Reed @ 2024-02-05 15:48 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 941 bytes --] > I know and expect that $((()) has its internal grammar. But 'let' seems ... naked ... for lack of a better word and it's a strain on grammatical rigor that it gets special, invisible favors. Well, it doesn't, really. Grammar-wise, let is treated as a normal command, which is why you need quoting to use special characters or white space with it. The ((...)) construct was added to the shell (and described in the KornShell book) as effectively a version of let that is quoted for you - that's where the special parsing comes in. let itself doesn't have that. It does evaluate its arguments in an arithmetic context, and is one of the main ways to achieve that effect, but it's not the only one, or even the only one outside ((...)). You've seen it kick in for variables declared as integers; it also shows up in array subscripts: zsh% ary=(a b c d e); i=2; j=1; k="i + j" zsh% echo $ary[$k] c -- Mark J. Reed <markjreed@gmail.com> [-- Attachment #2: Type: text/html, Size: 3401 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 1:14 ` Ray Andrews 2024-02-04 2:05 ` Lawrence Velázquez @ 2024-02-04 14:43 ` Mark J. Reed 2024-02-04 16:37 ` Ray Andrews 1 sibling, 1 reply; 25+ messages in thread From: Mark J. Reed @ 2024-02-04 14:43 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 1630 bytes --] On Sat, Feb 3, 2024 at 8:14 PM Ray Andrews <rayandrews@eastlink.ca> wrote: > 0 /usr/share/info 0 % var=abc; let var+=2; echo $var > 2 > > ... it looks like the shell is simply throwing away 'abc' and starting > afresh with an integer and then incrementing it. > That's not qutie what's happening. Arithmetic expressions interpret *all* variables as numbers, whether the variables are *declared* as integers or not. If a variable's value doesn't look like a number, it is interpreted as the *name *of another variable, which is then looked up recursively. If it gets to a variable that doesn't exist, the value is taken as 0. So, when you do any sort of assignment inside a *let* or *((*...*))* or array subscript or any other arithmetic context, the variable being assigned will *always* come out of it with a numeric value. But unless you've done a *declare -i *or *typeset -i*, it will not be stored as an integer; it will be converted back to a string that just happens to be all digits. What's the difference? Well, let's continue your example: *zsh%* var=abc; let var+=2; echo $var *2* *zsh%* var+=2; echo $var # note: no let *22* As you can see, outside of *let*, using *+=* *appended* to the variable instead of doing arithmetic. Because it's still a string. If you were to go in and declare it as an integer, then *+= *would have its arithmetic meaning even outside of explicit arithmetic context: *zsh% *typeset -i var *zsh% *var+=2; echo $var *24* But that's only because of the *typeset*. It doesn't happen automatically. -- Mark J. Reed <markjreed@gmail.com> [-- Attachment #2: Type: text/html, Size: 3448 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 14:43 ` Mark J. Reed @ 2024-02-04 16:37 ` Ray Andrews 2024-02-04 21:09 ` Lawrence Velázquez 0 siblings, 1 reply; 25+ messages in thread From: Ray Andrews @ 2024-02-04 16:37 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 1588 bytes --] On 2024-02-04 06:43, Mark J. Reed wrote: > > That's not qutie what's happening. Arithmetic expressions interpret > /all/ variables as numbers, whether the variables are /declared/ as > integers or not. If a variable's value doesn't look like a number, it > is interpreted as the /name /of another variable, which is then looked > up recursively. If it gets to a variable that doesn't exist, the value > is taken as 0. I get that. $(( abc ..... )) ... abc isn't a number therefore it's the name of a variable. However I did: % var=abc ... outside any (()) and the conversion happened 'retroactively' so to speak. % var=path; print -- $var path ... 'path' is just a string, there's no implicit conversion to a variable. Ergo: %var=abc ... seems to me the same. Later on abc becomes an integer name, and the string is lost > > ... it will be converted back to a string that just happens to be all > digits. What's the difference? Well, let's continue your example: > > *zsh%* var=abc; let var+=2; echo $var > *2* > *zsh%* var+=2; echo $var # note: no let > *22* > Right, I get that too. A string of digits is still a string. Anyway it goes back to my original speculation/question that implicit promotions/conversions do happen thus a 'demotion' -- in the case of that glob expansion -- is something that might at least be contemplated even if in fact the idea is unsound. As for me I think that taking a string and then using it as the name of an integer is a bit strange, but it is what it is and I won't crash into that problem again. [-- Attachment #2: Type: text/html, Size: 3251 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: for loop 'bad math expression' 2024-02-04 16:37 ` Ray Andrews @ 2024-02-04 21:09 ` Lawrence Velázquez 0 siblings, 0 replies; 25+ messages in thread From: Lawrence Velázquez @ 2024-02-04 21:09 UTC (permalink / raw) To: zsh-users On Sun, Feb 4, 2024, at 11:37 AM, Ray Andrews wrote: > I get that. $(( abc ..... )) ... abc isn't a number therefore it's the > name of a variable. However I did: > > % var=abc > ... outside any (()) and the conversion happened 'retroactively' so to speak. > > % var=path; print -- $var > path > ... 'path' is just a string, there's no implicit conversion to a > variable. Of course there isn't, because there is no arithmetic context there. If you'd run print -- $((var)) then "path" would have been referenced recursively. (And you almost certainly would have seen an error because the contents of "path" are unlikely to form a valid arithmetic expression.) > Ergo: > > %var=abc > ... seems to me the same. Later on abc becomes an integer name, and > the string is lost The string is never lost. Inspect the raw value of "var"; it does not change from "abc" unless you change it yourself. > Anyway it goes back to my original speculation/question that implicit > promotions/conversions do happen You still haven't demonstrated any situations where this occurs. All your examples have been broken, and your conjectures confused. -- vq ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2024-02-05 15:48 UTC | newest] Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-01-30 3:39 for loop 'bad math expression' Ray Andrews 2024-01-30 3:46 ` Ray Andrews 2024-01-30 4:04 ` Bart Schaefer 2024-01-30 4:06 ` Bart Schaefer 2024-01-30 4:17 ` Ray Andrews 2024-01-30 13:44 ` Ray Andrews 2024-01-30 14:30 ` Lawrence Velázquez 2024-02-03 23:52 ` Bart Schaefer 2024-02-04 1:14 ` Ray Andrews 2024-02-04 2:05 ` Lawrence Velázquez 2024-02-04 4:20 ` Bart Schaefer 2024-02-04 16:08 ` Ray Andrews 2024-02-04 20:56 ` Lawrence Velázquez 2024-02-04 15:51 ` Ray Andrews 2024-02-04 20:48 ` Lawrence Velázquez 2024-02-04 21:09 ` Bart Schaefer 2024-02-04 21:23 ` Bart Schaefer 2024-02-05 2:10 ` Bart Schaefer 2024-02-05 2:43 ` Mikael Magnusson 2024-02-05 2:50 ` Bart Schaefer 2024-02-05 15:21 ` Ray Andrews 2024-02-05 15:48 ` Mark J. Reed 2024-02-04 14:43 ` Mark J. Reed 2024-02-04 16:37 ` Ray Andrews 2024-02-04 21:09 ` Lawrence Velázquez
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).