* suprise with -= @ 2015-10-19 5:46 Ray Andrews 2015-10-19 18:35 ` Bart Schaefer 0 siblings, 1 reply; 14+ messages in thread From: Ray Andrews @ 2015-10-19 5:46 UTC (permalink / raw) To: Zsh Users test1 () { integer first=1 integer second=2 ((first+=second)) echo $first ((first-=second)) echo $first first+=second echo $first first-=second echo $first } 3 1 3 test1:15: command not found: first-=second 3 That's a bit of a surprise, why is zsh fussier with '-=' than with '+='? ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-19 5:46 suprise with -= Ray Andrews @ 2015-10-19 18:35 ` Bart Schaefer 2015-10-19 19:34 ` Ray Andrews 0 siblings, 1 reply; 14+ messages in thread From: Bart Schaefer @ 2015-10-19 18:35 UTC (permalink / raw) To: Zsh Users On Oct 18, 10:46pm, Ray Andrews wrote: } } That's a bit of a surprise, why is zsh fussier with '-=' than with '+='? Outside of the (( )), -= is not an assignment operator at all, because the default is to do either array or string assignment, and there is no sensible way to "subtract" one array or string from another. Conversely += is defined to mean "append", so it is a valid operator. I'd almost call it a bug that [outside of (( )) context] first+=second does arithmetic when $first is an integer. It ought to be either an error or forcibly convert $first to string and append "second". ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-19 18:35 ` Bart Schaefer @ 2015-10-19 19:34 ` Ray Andrews 2015-10-20 0:27 ` Bart Schaefer 0 siblings, 1 reply; 14+ messages in thread From: Ray Andrews @ 2015-10-19 19:34 UTC (permalink / raw) To: zsh-users On 10/19/2015 11:35 AM, Bart Schaefer wrote: > On Oct 18, 10:46pm, Ray Andrews wrote: > } > } That's a bit of a surprise, why is zsh fussier with '-=' than with '+='? > > Outside of the (( )), -= is not an assignment operator at all, because > the default is to do either array or string assignment, and there is > no sensible way to "subtract" one array or string from another. > > Conversely += is defined to mean "append", so it is a valid operator. > > I'd almost call it a bug that [outside of (( )) context] first+=second > does arithmetic when $first is an integer. It ought to be either an > error or forcibly convert $first to string and append "second". I've managed to suppress my gag reflex with all that arithmetic stuff--goes back to the need to declare variable types, which is what I'm trying to do with 'integer' and after that I'd expect both increment and decrement to behave the same way. I see what you mean tho--we can append strings but we can't un-append them (tho one might consider that as " first=${first%$second} " (not sure if I wrote that right, but you get me) ). For now I feel comforted to always use the (( )) because it's explicit and you can mercifully space things: (( first -= second )). Just to comment, I'd consider it very rude for any forcible conversions to occur. Better an error, tho again once one has declared an integer one might expect one's operators to behave consistently. We don't have warnings do we? In C, of course, if one is doing something strange the compiler doesn't stop you, but it will warn you. I once had great fun writing an encrypt function that performed arithmetic on strings--the compiler didn't like it, but it did what it was told. Na ... can't have warnings in interpreted stuff, tho there could be a proofreader ... ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-19 19:34 ` Ray Andrews @ 2015-10-20 0:27 ` Bart Schaefer 2015-10-21 2:55 ` Ray Andrews 2015-10-21 18:01 ` Ray Andrews 0 siblings, 2 replies; 14+ messages in thread From: Bart Schaefer @ 2015-10-20 0:27 UTC (permalink / raw) To: zsh-users On Oct 19, 12:34pm, Ray Andrews wrote: } } [...] declare variable types, which is what I'm trying to do with } 'integer' and after that I'd expect both increment and decrement to } behave the same way. The parser doesn't know that "first" is an integer, or even that it's a variable that was previously declared. This is perfectly legal: if (( RANDOM % 7 )) then integer first else declare first fi first+=second (Which is why I'm inclined to say it ought to always be string context when not explicitly math context, but it's probably way to late for that.) } I'd consider it very rude for any forcible conversions to occur. } Better an error, tho again once one has declared an integer one might } expect one's operators to behave consistently. Note: torch% integer first=1 second=2 torch% first+=(second) torch% echo $first 1 second This has silently forced $first to change into an array because of explicit array context; it did not interpret "(second)" as arithmetic parens. Also just to mess things up a bit more: torch% integer first=1 second=2 torch% third=first+second torch% print $third first+second torch% integer third torch% print $third 3 If something has a string value and you re-declare it integer, it does math on its string value. Doesn't happen for array to integer. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-20 0:27 ` Bart Schaefer @ 2015-10-21 2:55 ` Ray Andrews 2015-10-21 3:52 ` Bart Schaefer 2015-10-21 18:01 ` Ray Andrews 1 sibling, 1 reply; 14+ messages in thread From: Ray Andrews @ 2015-10-21 2:55 UTC (permalink / raw) To: zsh-users On 10/19/2015 05:27 PM, Bart Schaefer wrote: > On Oct 19, 12:34pm, Ray Andrews wrote: > } > } [...] declare variable types, which is what I'm trying to do with > } 'integer' and after that I'd expect both increment and decrement to > } behave the same way. > > The parser doesn't know that "first" is an integer, or even that it's > a variable that was previously declared. This is perfectly legal: > > if (( RANDOM % 7 )) > then integer first > else declare first > fi > first+=second Then what does 'integer' or 'typset -i' do? > (Which is why I'm inclined to say it ought to always be string context > when not explicitly math context, but it's probably way to late for that.) Given all these little gotchas, I think you are right. (()) is math, otherwise you're on thin ice. Still tho, surely 'integer' should be a typecast and not changeable, tho of course it's too late to do anything about that. I can't help but wonder what was going on in the minds of the guys who coded the first shells and decided to permit this sort of anarchy, I'm sure they had their reasons but since the shells are written in C, I'd have expected normal C discipline to set the standard. > } I'd consider it very rude for any forcible conversions to occur. > } Better an error, tho again once one has declared an integer one might > } expect one's operators to behave consistently. > > Note: > > torch% integer first=1 second=2 > torch% first+=(second) > torch% echo $first > 1 second > > This has silently forced $first to change into an array because of > explicit array context; it did not interpret "(second)" as arithmetic > parens. Well I guess that's the universal reality of shells, so I just hafta get used to it. Actually I am already more or less used to it. > > Also just to mess things up a bit more: > > torch% integer first=1 second=2 > torch% third=first+second > torch% print $third > first+second > torch% integer third > torch% print $third > 3 > > If something has a string value and you re-declare it integer, it does > math on its string value. Doesn't happen for array to integer. > Thanks for the examples, these are so educational. I'll play with them for several days. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-21 2:55 ` Ray Andrews @ 2015-10-21 3:52 ` Bart Schaefer 0 siblings, 0 replies; 14+ messages in thread From: Bart Schaefer @ 2015-10-21 3:52 UTC (permalink / raw) To: Ray Andrews, zsh-users On Oct 20, 7:55pm, Ray Andrews wrote: } Subject: Re: suprise with -= } } On 10/19/2015 05:27 PM, Bart Schaefer wrote: } > The parser doesn't know that "first" is an integer, or even that it's } > a variable that was previously declared. This is perfectly legal: } > } > if (( RANDOM % 7 )) } > then integer first } > else declare first } > fi } > first+=second } } Then what does 'integer' or 'typset -i' do? They declare that the internal representation of the variable should be an integer, so that integer formatting may be applied when the variable is converted back to a value with $first. } I can't help but wonder what was going on in the minds of the guys who } coded the first shells The first shells didn't have integers or arrays at all. They had only strings, and a few (external) programs like "expr" that could interpret strings of digits as numbers. Arrays came next and numbers/math last of all, so numbers must conform to the rules established when the shell was strings-only. Shells were never intended to look or behave anything like C (well, except for csh, but it was only supposed to look like C, not act like it, and it got a lot of other things wrong). ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-20 0:27 ` Bart Schaefer 2015-10-21 2:55 ` Ray Andrews @ 2015-10-21 18:01 ` Ray Andrews 2015-10-21 18:43 ` ZyX 2015-10-21 18:46 ` Bart Schaefer 1 sibling, 2 replies; 14+ messages in thread From: Ray Andrews @ 2015-10-21 18:01 UTC (permalink / raw) To: zsh-users On 10/19/2015 05:27 PM, Bart Schaefer wrote: > The parser doesn't know that "first" is an integer, or even that it's > a variable that was previously declared. That puzzles me. Have not all your examples demonstrated that the parser is aware of the type of the variable and that it will perform it's operations accordingly? test2 () { integer first=1 second=2 third=first+second print A $third integer third print B $third integer fourth=first+second print C $fourth } A first+second # 'third' is scalar so does the 'wrong' thing. B 0 # 'third' is now known to be integer by the 'print'. C 3 # 'fourth' is integer up front and remembered to be so. I see very clearly that the type can change silently or sometimes not change at all and just sorta 'do nothing': test1 () { integer first=1 string1=foo first+=string1 echo ${(t)first} echo "$first" } integer-local 1 # The addition does nothing at all, but no error is thrown. ... and "${(t) ...}" is surely the demonstration that types are remembered? I'm makinga deep error here, probably. > The first shells didn't have integers or arrays at all. They had only > strings, and a few (external) programs like "expr" that could interpret > strings of digits as numbers. Thanks. These 'history lessons' are invaluable (to me, anyway). If anything besides strings were never anticipated in the original design of shells,then integers would bea 'tack on' and one could see that the whole issue of declarations/typing would behandled poorly. The lesson is that one must be bloody careful. OTOH, whereas in Cif one wants to force a typecast it's a labor, whereas in zsh one can do it not onlyeffortlessly, but even invisibly. Powerful but dangerous.Caveat emptor. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-21 18:01 ` Ray Andrews @ 2015-10-21 18:43 ` ZyX 2015-10-22 15:29 ` Ray Andrews 2015-10-21 18:46 ` Bart Schaefer 1 sibling, 1 reply; 14+ messages in thread From: ZyX @ 2015-10-21 18:43 UTC (permalink / raw) To: Ray Andrews, zsh-users 21.10.2015, 21:02, "Ray Andrews" <rayandrews@eastlink.ca>: > On 10/19/2015 05:27 PM, Bart Schaefer wrote: >> The parser doesn't know that "first" is an integer, or even that it's >> a variable that was previously declared. > > That puzzles me. Have not all your examples demonstrated that the > parser is aware of the type of the variable and that it will perform > it's operations accordingly? > > test2 () > { > > integer first=1 second=2 > > third=first+second > print A $third > integer third > print B $third > > integer fourth=first+second > print C $fourth > > } > A first+second # 'third' is scalar so does the 'wrong' thing. > B 0 # 'third' is now known to be integer by the 'print'. > C 3 # 'fourth' is integer up front and remembered to > be so. > > I see very clearly that the type can change silently or sometimes not > change at all and just sorta 'do nothing': How is *parser* related? To make integer fourth=first+second set `fourth` to `3` it is *absolutely* not needed to parse this as integer(assign("fourth", plus("first", "second"))) . Just at the time of parsing you parse it as integer(assign("fourth", "first+second")) and at the time of *execution* you evaluate `first+second` as an expression. > > test1 () > > { > > integer first=1 > string1=foo > > first+=string1 > echo ${(t)first} > echo "$first" > > } > integer-local > 1 # The addition does nothing at all, but no error is thrown. > > ... and "${(t) ...}" is surely the demonstration that types are > remembered? I'm makinga deep error here, probably. Remembering types has *absolutely* nothing to do with parsing. ${(t)V} is executed at runtime, after parsing. Neither parser needs to know what is `V` and whether it is defined. Basically this happens in every dynamically typed language. (Though most statically typed language developers do not think that parsing two constructs differently depending on variable types is not a good idea; this does not prevent e.g. `foo.a` to be an error due to incorrect `foo` type, but this is checked after parsing stage and is always read as something like `getattr("foo", "a")`.) > >> The first shells didn't have integers or arrays at all. They had only >> strings, and a few (external) programs like "expr" that could interpret >> strings of digits as numbers. > > Thanks. These 'history lessons' are invaluable (to me, anyway). If > anything besides strings were never anticipated in the original design > of shells,then integers would bea 'tack on' and one could see that the > whole issue of declarations/typing would behandled poorly. The lesson > is that one must be bloody careful. OTOH, whereas in Cif one wants to > force a typecast it's a > labor, whereas in zsh one can do it not onlyeffortlessly, but even > invisibly. > Powerful but dangerous.Caveat emptor. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-21 18:43 ` ZyX @ 2015-10-22 15:29 ` Ray Andrews 2015-10-22 15:43 ` ZyX 0 siblings, 1 reply; 14+ messages in thread From: Ray Andrews @ 2015-10-22 15:29 UTC (permalink / raw) To: zsh-users On 10/21/2015 11:43 AM, ZyX wrote: > and at the time of *execution* you evaluate `first+second` as an > expression. Ok, I think I begin to see where I'm going wrong. I'm extending 'parsing' in my head into what only happens at execution. Another difference between a compiled language vs. an interpreted one. I guess parsing, in an interpreted language, is strictly speaking a much simple matter. At run time more work is done. Thanks. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-22 15:29 ` Ray Andrews @ 2015-10-22 15:43 ` ZyX 2015-10-22 16:02 ` Ray Andrews 2015-10-22 23:56 ` Bart Schaefer 0 siblings, 2 replies; 14+ messages in thread From: ZyX @ 2015-10-22 15:43 UTC (permalink / raw) To: Ray Andrews, zsh-users 22.10.2015, 18:31, "Ray Andrews" <rayandrews@eastlink.ca>: > On 10/21/2015 11:43 AM, ZyX wrote: > >> and at the time of *execution* you evaluate `first+second` as an >> expression. > > Ok, I think I begin to see where I'm going wrong. I'm extending > 'parsing' in my head into what only happens at execution. Another > difference between a compiled language vs. an interpreted one. I guess > parsing, in an interpreted language, is strictly speaking a much simple > matter. At run time more work is done. Thanks. It is not always wrong, BTW. E.g. VimL has no “parsing” stage, it always directly *executes* the input string, doing any parsing in process. This is why e.g. when calling :let var=[system("echo bar>baz"), file `baz` will appear, but `var` will not get assigned due to parsing error: VimL executor does not see absense of `]` at the time it is executing `system()` call. Also meaning of :echo var.val depends on `var` variable type (it may either be `var . val` (string concat) or `var['val']` (dictionary index)). Though I know no language implementations other then VimL (and, maybe, tcsh: have not actually seen its source code, but it looks like it is also executed in-place) that do not have the parsing stage. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-22 15:43 ` ZyX @ 2015-10-22 16:02 ` Ray Andrews 2015-10-22 23:56 ` Bart Schaefer 1 sibling, 0 replies; 14+ messages in thread From: Ray Andrews @ 2015-10-22 16:02 UTC (permalink / raw) To: ZyX, zsh-users On 10/22/2015 08:43 AM, ZyX wrote: > 22.10.2015, 18:31, "Ray Andrews" <rayandrews@eastlink.ca>: > > It is not always wrong, BTW. E.g. VimL has no “parsing” stage, it always directly *executes* the input string, doing any parsing in process. This is why e.g. when calling > > :let var=[system("echo bar>baz"), > > file `baz` will appear, but `var` will not get assigned due to parsing error: VimL executor does not see absense of `]` at the time it is executing `system()` call. Also meaning of Well then I should be grateful for whatever parsing zsh does--at least it picks up clear errors in syntax. But as Bart says, semantics is not the same thing. One can think one understands these things but still have a brain full of deep errors. If I'd been involved in this 20 years ago I'd have written: "The Tao of shells--why everything a C coder thinks he knows about programming ain't necessarily so." ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-22 15:43 ` ZyX 2015-10-22 16:02 ` Ray Andrews @ 2015-10-22 23:56 ` Bart Schaefer 2015-10-23 7:34 ` Daniel Shahaf 1 sibling, 1 reply; 14+ messages in thread From: Bart Schaefer @ 2015-10-22 23:56 UTC (permalink / raw) To: zsh-users On Oct 22, 6:43pm, ZyX wrote: } } Though I know no language implementations other then VimL (and, maybe, } tcsh: have not actually seen its source code, but it looks like it is } also executed in-place) that do not have the parsing stage. Yes, (t)csh also executes in place, or close to it. Csh parses one line at a time, executes it, then parses the next line. It's not quite as bad as VimL, but it means that e.g. loops within scripts are implemented by using fseek to rewind the file pointer to the beginning of the loop. You can create some really entertaining self-modifying scripts in csh by having the script rewrite parts of its own source file before they are read (or re-read, if looping). Csh is like Gromit in "The Wrong Trousers", laying down his tracks the instant before the train runs across them. VimL apparently lays down the individual railroad ties. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-22 23:56 ` Bart Schaefer @ 2015-10-23 7:34 ` Daniel Shahaf 0 siblings, 0 replies; 14+ messages in thread From: Daniel Shahaf @ 2015-10-23 7:34 UTC (permalink / raw) To: zsh-users Bart Schaefer wrote on Thu, Oct 22, 2015 at 16:56:26 -0700: > On Oct 22, 6:43pm, ZyX wrote: > } > } Though I know no language implementations other then VimL (and, maybe, > } tcsh: have not actually seen its source code, but it looks like it is > } also executed in-place) that do not have the parsing stage. > > Yes, (t)csh also executes in place, or close to it. Csh parses one line > at a time, executes it, then parses the next line. It's not quite as > bad as VimL, but it means that e.g. loops within scripts are implemented > by using fseek to rewind the file pointer to the beginning of the loop. > > You can create some really entertaining self-modifying scripts in csh by > having the script rewrite parts of its own source file before they are > read (or re-read, if looping). > > Csh is like Gromit in "The Wrong Trousers", laying down his tracks the > instant before the train runs across them. VimL apparently lays down > the individual railroad ties. TeX is also a lot of fun: % cat texput.tex xmessage{this is file contents} \catcode`x=0\relax xmessage{this is a compile-time message} xbye % tex texput.tex This is TeX, Version 3.14159265 (TeX Live 2015/dev/Debian) (preloaded format=tex) (./texput.tex this is a compile-time message [1] ) Output written on texput.dvi (1 page, 244 bytes). Transcript written on texput.log. % dvi2tty texput.dvi | grep . xmessagethis is file contents 1 % I suppose you might say that TeX not only lays down the individual railroad ties like VimL, but also allows each tie to specify the dimensions and color of the next tie... Daniel (tokenization is changeable at runtime; I made x equivalent to backslash, so, for instance, the last line invokes \bye) ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: suprise with -= 2015-10-21 18:01 ` Ray Andrews 2015-10-21 18:43 ` ZyX @ 2015-10-21 18:46 ` Bart Schaefer 1 sibling, 0 replies; 14+ messages in thread From: Bart Schaefer @ 2015-10-21 18:46 UTC (permalink / raw) To: zsh-users On Oct 21, 11:01am, Ray Andrews wrote: } Subject: Re: suprise with -= } } On 10/19/2015 05:27 PM, Bart Schaefer wrote: } > The parser doesn't know that "first" is an integer, or even that it's } > a variable that was previously declared. } That puzzles me. Have not all your examples demonstrated that the } parser is aware of the type of the variable and that it will perform } it's operations accordingly? No. Parser is syntax, not semantics. It knows "x=y" has a valid shape, and to create code to invoke an assignment at run time, but not what the assignment will do with x or y when run. You can think of "third=first+second" as syntactic sugar for the command "typeset third=first+second" -- it's the command that knows the type of the variable, not the parser. ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2015-10-23 7:34 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-10-19 5:46 suprise with -= Ray Andrews 2015-10-19 18:35 ` Bart Schaefer 2015-10-19 19:34 ` Ray Andrews 2015-10-20 0:27 ` Bart Schaefer 2015-10-21 2:55 ` Ray Andrews 2015-10-21 3:52 ` Bart Schaefer 2015-10-21 18:01 ` Ray Andrews 2015-10-21 18:43 ` ZyX 2015-10-22 15:29 ` Ray Andrews 2015-10-22 15:43 ` ZyX 2015-10-22 16:02 ` Ray Andrews 2015-10-22 23:56 ` Bart Schaefer 2015-10-23 7:34 ` Daniel Shahaf 2015-10-21 18:46 ` 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).