* unexpected unmodified variable @ 2022-10-06 19:07 Ray Andrews 2022-10-06 19:28 ` Peter Stephenson 0 siblings, 1 reply; 9+ messages in thread From: Ray Andrews @ 2022-10-06 19:07 UTC (permalink / raw) To: Zsh Users func2 () { count=2 echo from func2: $count } func1 () { local count=1 func2 echo from func1: $count count=1 var=$( func2 ) echo from func1: $count echo var is: $var } $ func1 from func2: 2 from func1: 2 from func1: 1 var is: from func2: 2 ... This catches me by surprise; when " var =$( func2 ) " happens I'm expecting 'func2' to do everything it does including reset 'count' to '2'. Why doesn't it, and is there any way to solve that? Hacking around: func1 () { local count=1 func2 > /dev/null func2 } ... performs as I'm wanting it to but it's a bit disgusting. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: unexpected unmodified variable 2022-10-06 19:07 unexpected unmodified variable Ray Andrews @ 2022-10-06 19:28 ` Peter Stephenson 2022-10-06 21:58 ` Ray Andrews 0 siblings, 1 reply; 9+ messages in thread From: Peter Stephenson @ 2022-10-06 19:28 UTC (permalink / raw) To: Zsh Users On Thu, 2022-10-06 at 12:07 -0700, Ray Andrews wrote: > ... This catches me by surprise; when " var =$( func2 ) " happens I'm > expecting 'func2' to do everything it does including reset 'count' to > '2'. Why doesn't it, and is there any way to solve that? $(...) causes a shell to be forked --- it runs in a different process, prints its output to somewhere that's collected by the main shell, then exits. So the internal effects disapper. There's no simple workaround if you want the output directly other than what you tried. You can make the function set a variable instead. % foo() { typeset -g $1="this is returned from foo"; } % foo myvar % print $myvar this is returned from foo The -g in the typeset tells it not to create a local scope within foo. Returning stuff in a sane way is a real weakness in shells. pws ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: unexpected unmodified variable 2022-10-06 19:28 ` Peter Stephenson @ 2022-10-06 21:58 ` Ray Andrews 2022-10-07 0:36 ` Bart Schaefer 0 siblings, 1 reply; 9+ messages in thread From: Ray Andrews @ 2022-10-06 21:58 UTC (permalink / raw) To: zsh-users On 2022-10-06 12:28, Peter Stephenson wrote: > $(...) causes a shell to be forked --- it runs in a different process, > prints its output to somewhere that's collected by the main shell, > then exits. So the internal effects disapper. > > > Returning stuff in a sane way is a real weakness in shells. > > pws Thanks Peter, I sorta suspected it was one of those subshell issues. I must have gotten the invocation wrong cuz I had no luck making the variable global. I ended up sending the output to a bleeding file and then rereading that. There otta be a better way. > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: unexpected unmodified variable 2022-10-06 21:58 ` Ray Andrews @ 2022-10-07 0:36 ` Bart Schaefer 2022-10-07 1:37 ` Ray Andrews 0 siblings, 1 reply; 9+ messages in thread From: Bart Schaefer @ 2022-10-07 0:36 UTC (permalink / raw) To: Ray Andrews; +Cc: zsh-users On Thu, Oct 6, 2022 at 2:59 PM Ray Andrews <rayandrews@eastlink.ca> wrote > > On 2022-10-06 12:28, Peter Stephenson wrote: > > > Returning stuff in a sane way is a real weakness in shells. Shrug; shells were originally designed to facilitate text processing by small independent single-purpose applications. Everything else is a bolt-on. > I ended up sending the output to a bleeding file and > then rereading that. There otta be a better way. if you're only dealing with numbers, then the bolted-on math-function capability can do "real" return values with locally-visible side-effects. func2 () { (( count=2 )) # math op defines return value echo set by func2: $count } func1 () { local count=1 func2 echo got from func2: $count count=1 var=$(( func2() )) # note parens echo seen from func1: $count echo var is: $var # now integer not text } functions -M func2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: unexpected unmodified variable 2022-10-07 0:36 ` Bart Schaefer @ 2022-10-07 1:37 ` Ray Andrews 2022-10-07 4:36 ` Bart Schaefer 0 siblings, 1 reply; 9+ messages in thread From: Ray Andrews @ 2022-10-07 1:37 UTC (permalink / raw) To: zsh-users On 2022-10-06 17:36, Bart Schaefer wrote: > Shrug; shells were originally designed to facilitate text processing > by small independent single-purpose applications. Everything else is > a bolt-on. Yes, the ultimate example of accretion. Playing with that, it seems the last math operation gets to be the rv unless you set a return value, which seems to not go away: functions -M func2 func2 () { echo func2 here! count=2 #return 3 } func1 () { local count=1 var=$(( func2() )) echo var is: $var, count is $count } $ func1 func2 here! var is: 3, count is 2 ... I had : "return 3" active, but commenting it out didn't seem to change anything which is puzzling. Anyway, it seems that 'count' can be a normal variable just so long as 'func2' is called mathematically. It's not very intuitive but an interesting party trick just the same. Or am I missing something as usual? ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: unexpected unmodified variable 2022-10-07 1:37 ` Ray Andrews @ 2022-10-07 4:36 ` Bart Schaefer 2022-10-07 15:28 ` Ray Andrews 0 siblings, 1 reply; 9+ messages in thread From: Bart Schaefer @ 2022-10-07 4:36 UTC (permalink / raw) To: Ray Andrews; +Cc: zsh-users On Thu, Oct 6, 2022 at 6:37 PM Ray Andrews <rayandrews@eastlink.ca> wrote: > > Playing with that, it seems the last math operation gets to be the rv > unless you set a return value Yes, that's documented. Interpreting the argument of "return" counts as a math operation, so the math value of a "functions -M" function really is always the last math operation. > ... I had : "return 3" active, but commenting it out didn't seem to > change anything which is puzzling. I think you must have typo'd something somewhere. Add "functions -t func2" so you can see a trace of what's executing. > Anyway, it seems that 'count' can be > a normal variable just so long as 'func2' is called mathematically. That's not exactly the point ... what kind of variable "count" is, in this case, doesn't matter. What matters is that $(( func2() )) runs in the current shell, not in a subshell. In case it wasn't obvious, $(( func2 )) treats func2 as the name of a variable, not a function, so it doesn't run func2 at all. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: unexpected unmodified variable 2022-10-07 4:36 ` Bart Schaefer @ 2022-10-07 15:28 ` Ray Andrews 2022-10-07 20:00 ` Bart Schaefer 0 siblings, 1 reply; 9+ messages in thread From: Ray Andrews @ 2022-10-07 15:28 UTC (permalink / raw) To: zsh-users [-- Attachment #1: Type: text/plain, Size: 4418 bytes --] On 2022-10-06 21:36, Bart Schaefer wrote: > Yes, that's documented. Interpreting the argument of "return" counts > as a math operation, so the math value of a "functions -M" function > really is always the last math operation. Bart, can you point me to something where I can read up on this 'functions -M', I was just using it on faith and because things broke without it. I've never used that before and never seemed to miss it. In the manual I read: By default the function is implemented by a shell function of the same name; if shellfn is specified it gives the name of the corresponding shell func‐ tion while mathfn remains the name used in arithmetical expressions. The name of the function in $0 is mathfn (not shellfn as would usually be the case), provided the option FUNCTION_ARGZERO is in effect. The positional parameters in the shell function correspond to the arguments of the mathe‐ matical function call. The result of the last arithmetical expression eval‐ uated inside the shell function (even if it is a form that normally only re‐ turns a status) gives the result of the mathematical function. ... which might just be the most impenetrable bit of computer bafflegab I've ever read, I can't get past the first sentence. You have to be Peter to understand that. > I think you must have typo'd something somewhere. Add "functions -t > func2" so you can see a trace of what's executing. No typo, everything is copied and pasted without edit: The file 'test1': #!/usr/bin/zsh functions -M func2 func2 () { functions -t func2 echo func2 here! count=2 #return 3 } func1 () { functions -t func2 local count=1 var=$(( func2() )) # Count = 1, no effect: #var=$( func2 ) echo var is: $var, count is $count } The run: 0 /aWorking/Zsh/Source/Wk 3 $ . test1; func1 +func2:2:>functions -t func2 +func2:3:>echo func2 'here!' func2 here! +func2:4:>count=2 var is: 0, count is 2 <<< With 'return 3' commented out. 0 /aWorking/Zsh/Source/Wk 3 $ . test1; func1 +func2:2:>functions -t func2 +func2:3:>echo func2 'here!' func2 here! +func2:4:>count=2 +func2:5:>return 3 var is: 3, count is 2 <<< With 'return 3' active. 0 /aWorking/Zsh/Source/Wk 3 $ . test1; func1 +func2:2:>functions -t func2 +func2:3:>echo func2 'here!' func2 here! +func2:4:>count=2 var is: 3, count is 2 <<< With 'return 3' commented out again. > this case, doesn't matter. What matters is that $(( func2() )) runs > in the current shell, not in a subshell. Right, I understand that. So long as there's math involved, there's no subshell. BTW, if I modify func2: func2 () { functions -t func2 echo func2 here! #integer count=2 #return 3 } ... the same pattern results: '# integer count=2': and count is unchanged in func1, var = 0. 'integer count=2': and count is unchanged in func1 but var = 2. I force it to be a math op. The 'integer count' seems to be a new variable so the original is unchanged, that's clear. '# integer count=2': and var is '2'. func2 retains the previous return value even thou the active line is commented out (again). Unless I'm making some kind of mistake, it seems buggy to me, the rv of func2 is floating unchanged somewhere. When I explicitly change it, it changes, but then the new value floats there too. I've done it a dozen times, I don't think I'm wrong. I have to start a new shell to erase that rv. Or is this some bizarre local issue here? Tho I do wonder why '$(( ))' is 'local' and '$( )' spawns a subshell, dunno, maybe there's a good reason for that but one might wish for some method of asking '$( )' to run 'local' too, so that my original issue wouldn't come up. I appreciate that this kind of thing is so deep in the way the shell runs that it might be next to impossible even if anyone but me was interested in it. Still: "setopt NO_SUBSHELL" might be very useful. > > In case it wasn't obvious, $(( func2 )) treats func2 as the name of a > variable, not a function, so it doesn't run func2 at all. Yes, that's clear. '$(( func2() ))' is a math operation -- grab the return value, which is whatever the last math operation was. '$(( func2 ))' is ... basically nothing. > [-- Attachment #2: Type: text/html, Size: 6702 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: unexpected unmodified variable 2022-10-07 15:28 ` Ray Andrews @ 2022-10-07 20:00 ` Bart Schaefer 2022-10-07 21:59 ` Ray Andrews 0 siblings, 1 reply; 9+ messages in thread From: Bart Schaefer @ 2022-10-07 20:00 UTC (permalink / raw) To: Ray Andrews; +Cc: zsh-users On Fri, Oct 7, 2022 at 8:28 AM Ray Andrews <rayandrews@eastlink.ca> wrote: > > By default the function is implemented by a shell function of the same name; if > shellfn is specified it gives the name of the corresponding shell function > while mathfn remains the name used in arithmetical expressions. As with widgets, you can have a math function named X that's implemented by a shell function named Y. The default is that if the shell function is Y, then the math function is also Y. > The name > of the function in $0 is mathfn (not shellfn as would usually be the case), > provided the option FUNCTION_ARGZERO is in effect. This is just explaining how $0 works in case you're trying to have a function that references itself by name. > The positional > parameters in the shell function correspond to the arguments of the mathe‐ > matical function call. If you write $(( func2(a,b,c) )) then inside func2, $1 == a, $2 == b, $3 == c "Positional parameters" always means $1, $2, etc., that's not math-function-specific, it's just shell terminology. > The result of the last arithmetical expression eval‐ > uated inside the shell function (even if it is a form that normally only re‐ > turns a status) gives the result of the mathematical function. The parenthetical refers to the fact that some math operations are true/false, e.g. (( x > 12)) "is a form that only returns a status". Omitting that, the rest of the sentence should be clear. > ... which might just be the most impenetrable bit of computer bafflegab I've ever read, I can't get past the first sentence. Seriously? This is all using phrases that refer to concepts appearing elsewhere throughout the zsh manual. > You have to be Peter to understand that. Well, he did write it. > No typo, everything is copied and pasted without edit: Oh. Given the way you wrote func2, if you remove the return statement there are NO math expressions in func2 at all, so $(( func2() )) is [except for side-effects] a no-op, and the assignment in var=$(( func2() )) is just skipped, leaving the previous value of $var unchanged. If you turn the count=2 assignment into a math expression, either by your "integer count=2" test or by using (( count=2 )), then $(( func2() )) returns the value from that. It is a bit weird that var=$((...)) does nothing at all in that circumstance, I would have expected it either to assign empty string to $var or to have a nonzero $? as a result. Unanticipated edge case, possible bug. > Tho I do wonder why '$(( ))' is 'local' and '$( )' spawns a subshell $(...) spawns a subshell because stdin/stdout text is passed from one process to another using pipes, and if a process has a pipe to itself it can deadlock trying to read something it hasn't written yet (or write something there isn't room for because not enough has been read yet). $((...)) looks that way by analogy to ((...)), not by analogy to $(...). > one might wish for some method of asking '$( )' to run 'local' too "Local" text substitution is what ordinary $param references are for ... $(...) specifically means to use processes and pipes. That said, a still-missing feature in zsh is the ability to tie a function to a variable so that referencing the variable as $foo invokes the function that's tied to it, to produce the effect you're asking for. Ksh has a syntax for that. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: unexpected unmodified variable 2022-10-07 20:00 ` Bart Schaefer @ 2022-10-07 21:59 ` Ray Andrews 0 siblings, 0 replies; 9+ messages in thread From: Ray Andrews @ 2022-10-07 21:59 UTC (permalink / raw) To: zsh-users On 2022-10-07 13:00, Bart Schaefer wrote: > ... which might just be the most impenetrable bit of computer > bafflegab I've ever read, I can't get past the first sentence. > Seriously? This is all using phrases that refer to concepts appearing > elsewhere throughout the zsh manual. True ... which makes the manual hard to understand. It's a language unto itself. What would be helpful is some sort of introduction to zsh-speak. Mind, I expect all the shells have about the same jargon. But believe me, when you don't know the lingo it's impenetrable. > > Oh. Given the way you wrote func2, if you remove the return statement > there are NO math expressions in func2 at all, so $(( func2() )) is > [except for side-effects] a no-op, and the assignment in var=$(( > func2() )) is just skipped, leaving the previous value of $var > unchanged. Ah! ... yes, why would it change? nothing has touched it. I was expecting func2 to somehow cough up a null value setting 'var=0' but it's not illogical that it coughs up ... nothing ... therefore there is no assignment and 'var' does not change. I get it. > "Local" text substitution is what ordinary $param references are for > ... $(...) specifically means to use processes and pipes. That said, > a still-missing feature in zsh is the ability to tie a function to a > variable so that referencing the variable as $foo invokes the function > that's tied to it, to produce the effect you're asking for. Ksh has a > syntax for that. > Well you'd know. Anyway as usual the functionality I was looking for is there even if it didn't look like I expected. By now I should have a permanent understanding of this stuff not keep relapsing. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2022-10-07 21:59 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-10-06 19:07 unexpected unmodified variable Ray Andrews 2022-10-06 19:28 ` Peter Stephenson 2022-10-06 21:58 ` Ray Andrews 2022-10-07 0:36 ` Bart Schaefer 2022-10-07 1:37 ` Ray Andrews 2022-10-07 4:36 ` Bart Schaefer 2022-10-07 15:28 ` Ray Andrews 2022-10-07 20:00 ` Bart Schaefer 2022-10-07 21:59 ` Ray Andrews
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).