* Bug with unset variables @ 2020-11-11 15:57 Felipe Contreras 2020-11-11 16:13 ` Roman Perepelitsa 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-11 15:57 UTC (permalink / raw) To: zsh-workers Hello, It's obvious what this code should do: foo () { typeset var echo "var: '${var-other}'" } However, zsh throws an empty string. I tried different emulations, like ksh, and the same thing happens, even though in ksh the right output (other) is shown. I also tried with the other unnamable shell, and the correct output is shown. Only zsh does something different. My version is zsh 5.8. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 15:57 Bug with unset variables Felipe Contreras @ 2020-11-11 16:13 ` Roman Perepelitsa 2020-11-11 16:56 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Roman Perepelitsa @ 2020-11-11 16:13 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 4:57 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > Hello, > > It's obvious what this code should do: > > foo () { > typeset var > echo "var: '${var-other}'" > } When foo is invoked, based on the documentation for typeset, I would expect it to print "var: ''". Except as noted below for control flags that change the behav- ior, a parameter is created for each name that does not already refer to one. And indeed that's how foo behaves when I invoke it in zsh 5.8. > I also tried with the other unnamable shell, and the correct output is shown. I confirm that in bash 5.0.17 function foo prints "var: 'other'". However, I'm not sure whether this behavior agrees with the documentation. From `help declare`: Declare variables and give them attributes. [...] When used in a function, `declare' makes NAMEs local, as with the `local' command. From `help local`: Create a local variable called NAME, and give it VALUE. As far as I can tell, there is no indication anywhere in the documentation that omitting =VALUE will cause `local` to not create a variable in bash. Do you believe the behavior of bash is expected while zsh behaves incorrectly? If so, why? Roman. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 16:13 ` Roman Perepelitsa @ 2020-11-11 16:56 ` Felipe Contreras 2020-11-11 17:02 ` Roman Perepelitsa 2020-11-11 17:02 ` Peter Stephenson 0 siblings, 2 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-11 16:56 UTC (permalink / raw) To: Roman Perepelitsa; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 10:13 AM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > On Wed, Nov 11, 2020 at 4:57 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > Hello, > > > > It's obvious what this code should do: > > > > foo () { > > typeset var > > echo "var: '${var-other}'" > > } > > When foo is invoked, based on the documentation for typeset, I would > expect it to print "var: ''". My main concern is not the documentation of typeset, but useful code. The primary reason for why typeset exists is to set the scope of a variable. Especially so when using "local". If I actually do something on the foo() function: typeset var [[ -n "$1" ]] && var=$1 echo "var: '${var-other}'" I would expect two things: 1) var is not set when I exit the function, and 2) var is not set until I specifically set it. I can get both in ksh and bash, but not in zsh. In zsh I have to choose either 1) with typeset, or 2) by removing typeset. How do you suggest I get both in zsh? > Except as noted below for control flags that change the behav- > ior, a parameter is created for each name that does not already > refer to one. > > And indeed that's how foo behaves when I invoke it in zsh 5.8. It is possible to "create" a parameter without value (indeed that's what happens in other shells), the documentation doesn't say anything about assigning it a default empty string as value. > > I also tried with the other unnamable shell, and the correct output is shown. > From `help local`: > > Create a local variable called NAME, and give it VALUE. > > As far as I can tell, there is no indication anywhere in the > documentation that omitting =VALUE will cause `local` to not create a > variable in bash. The documentation makes it obvious that: local name Creates a local variable called "name". And: local name=value Creates a local variable called "name", and gives it "value" as its value. If you omit the value, then it doesn't assign it any value. As is the case in countless languages; declaring a variable without specifying any value assigns it the value of null (or "unset" in shell lingo). > Do you believe the behavior of bash is expected while zsh behaves > incorrectly? If so, why? Yes, and ksh also behaves correctly. As stated above, it's the only behavior that makes sense. Otherwise you cannot declare a local variable that is unset. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 16:56 ` Felipe Contreras @ 2020-11-11 17:02 ` Roman Perepelitsa 2020-11-11 18:03 ` Felipe Contreras 2020-11-11 17:02 ` Peter Stephenson 1 sibling, 1 reply; 53+ messages in thread From: Roman Perepelitsa @ 2020-11-11 17:02 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 5:56 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > If I actually do something on the foo() function: > > typeset var > [[ -n "$1" ]] && var=$1 > echo "var: '${var-other}'" > > I would expect two things: 1) var is not set when I exit the function, > and 2) var is not set until I specifically set it. > > I can get both in ksh and bash, but not in zsh. In zsh I have to > choose either 1) with typeset, or 2) by removing typeset. > > How do you suggest I get both in zsh? Add `unset var` right after `typeset var`. Roman. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 17:02 ` Roman Perepelitsa @ 2020-11-11 18:03 ` Felipe Contreras 2020-11-11 18:16 ` Roman Perepelitsa 2020-11-11 18:36 ` Bart Schaefer 0 siblings, 2 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-11 18:03 UTC (permalink / raw) To: Roman Perepelitsa; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 11:02 AM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > On Wed, Nov 11, 2020 at 5:56 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > If I actually do something on the foo() function: > > > > typeset var > > [[ -n "$1" ]] && var=$1 > > echo "var: '${var-other}'" > > > > I would expect two things: 1) var is not set when I exit the function, > > and 2) var is not set until I specifically set it. > > > > I can get both in ksh and bash, but not in zsh. In zsh I have to > > choose either 1) with typeset, or 2) by removing typeset. > > > > How do you suggest I get both in zsh? > > Add `unset var` right after `typeset var`. And what is the reason why this is not the default? Not only does this behavior differ from all other shells, but basically all languages. Either way, if "emulate ksh" is supposed to emulate ksh, then it's not working properly in this instance. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 18:03 ` Felipe Contreras @ 2020-11-11 18:16 ` Roman Perepelitsa 2020-11-11 20:42 ` Felipe Contreras 2020-11-11 18:36 ` Bart Schaefer 1 sibling, 1 reply; 53+ messages in thread From: Roman Perepelitsa @ 2020-11-11 18:16 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 7:03 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > And what is the reason why this is not the default? I don't know, I'm fairly new to zsh myself. All I can say is that the behavior of zsh feels more natural to me. > Not only does this behavior differ from all other shells, but > basically all languages. All languages? That seems exaggerated. How about this? int var; How many languages will set `var` to null here? Is it all of them? In the morally-equivalent shell code, bash does but zsh doesn't: typeset -i var echo $var I don't know which of these languages conforms to the majority opinion but neither can claim to do what *all* languages do. FWIW, I rely on this behavior of zsh in my code (namely, that `typeset -i var` sets `var` to 0). Roman. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 18:16 ` Roman Perepelitsa @ 2020-11-11 20:42 ` Felipe Contreras 2020-11-12 0:20 ` Mikael Magnusson 2020-11-12 8:45 ` Roman Perepelitsa 0 siblings, 2 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-11 20:42 UTC (permalink / raw) To: Roman Perepelitsa; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 12:17 PM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > On Wed, Nov 11, 2020 at 7:03 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > And what is the reason why this is not the default? > > I don't know, I'm fairly new to zsh myself. All I can say is that the > behavior of zsh feels more natural to me. Why would typeset var feel natural to be the same as typeset var="" ? If I wanted the second, I would type the second. Why does it feel natural to assign a value of a certain type, when no value was specified? > > Not only does this behavior differ from all other shells, but > > basically all languages. > > All languages? That seems exaggerated. How about this? > > int var; You are specifying a type. I obviously meant all languages where you can do the equivalent of "declare var" (without a type). That being said, the most similar to shell's "declare var" in C is "char *var" which defaults to null on most systems. > How many languages will set `var` to null here? Is it all of them? Pretty much, yeah. Do you want me to investigate and list them? Would the result of that investigation change the view of zsh developers? > In the morally-equivalent shell code, bash does but zsh doesn't: > > typeset -i var > echo $var In this case it might make sense to initialize to 0, since that's the only sensible default for an integer, but consider these: typeset -i int typeset -a array typeset -A hash typeset -F float In all these it should be obvious what would be the sensible default, but this: typeset var Does not specify any type (or any value), so why would you assign a value of a possibly wrong type? It becomes more obvious when you print the declaration at each step: typeset var typeset -p var var=() typeset -p var In bash, we get something sensible: declare -- var # no type specified declare -a var=() Not so in zsh: typeset var='' # why a string? typeset -a var=( ) Not only is it inconsistent superficially, but also internally, since strings are considered "scalar", but that is just another word for "variable". An integer is also a scalar. So the word "scalar" doesn't really explain any type (only that it is a single value). > I don't know which of these languages conforms to the majority opinion > but neither can claim to do what *all* languages do. It is the most sensible thing to do, so I bet at least 99.9% of languages do this. It is also good, desirable, and consistent, that this: typeset var typeset -p var is a roundtrip, which happens in bash, but not so in zsh. > FWIW, I rely on this behavior of zsh in my code (namely, that `typeset > -i var` sets `var` to 0). That may make sense, because you are specifying a type, but "typeset var" doesn't specify a type. Apples and oranges. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 20:42 ` Felipe Contreras @ 2020-11-12 0:20 ` Mikael Magnusson 2020-11-12 1:10 ` Felipe Contreras 2020-11-12 8:45 ` Roman Perepelitsa 1 sibling, 1 reply; 53+ messages in thread From: Mikael Magnusson @ 2020-11-12 0:20 UTC (permalink / raw) To: Zsh hackers list On 11/11/20, Felipe Contreras <felipe.contreras@gmail.com> wrote: > On Wed, Nov 11, 2020 at 12:17 PM Roman Perepelitsa > <roman.perepelitsa@gmail.com> wrote: >> > Not only does this behavior differ from all other shells, but >> > basically all languages. >> >> All languages? That seems exaggerated. How about this? >> >> int var; > > You are specifying a type. I obviously meant all languages where you > can do the equivalent of "declare var" (without a type). > > That being said, the most similar to shell's "declare var" in C is > "char *var" which defaults to null on most systems. This is certainly not true, just for the record. Variables in global or static scope are initialized to 0 regardless of type, whereas others are uninitialized (meaning they contain garbage, not that they magically know that they haven't been assigned to). -- Mikael Magnusson ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 0:20 ` Mikael Magnusson @ 2020-11-12 1:10 ` Felipe Contreras 0 siblings, 0 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-12 1:10 UTC (permalink / raw) To: Mikael Magnusson; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 6:20 PM Mikael Magnusson <mikachu@gmail.com> wrote: > On 11/11/20, Felipe Contreras <felipe.contreras@gmail.com> wrote: > > That being said, the most similar to shell's "declare var" in C is > > "char *var" which defaults to null on most systems. > > This is certainly not true, just for the record. Variables in global > or static scope are initialized to 0 regardless of type, whereas > others are uninitialized (meaning they contain garbage, not that they > magically know that they haven't been assigned to). The C standard says accessing an uninitialized variable results in *undefined* behavior, it doesn't say the variable *must* contain garbage. The variable *may* contain garbage, but not necessarily so. However, "static char *var" is *always* initialized to null. Either way, what *never* happens is var pointing to an empty string. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 20:42 ` Felipe Contreras 2020-11-12 0:20 ` Mikael Magnusson @ 2020-11-12 8:45 ` Roman Perepelitsa 2020-11-12 10:47 ` Peter Stephenson 2020-11-12 18:46 ` Felipe Contreras 1 sibling, 2 replies; 53+ messages in thread From: Roman Perepelitsa @ 2020-11-12 8:45 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 9:42 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > > typeset -i var > > echo $var > > In this case it might make sense to initialize to 0, since that's the > only sensible default for an integer, but consider these: > > typeset -i int > typeset -a array > typeset -A hash > typeset -F float > > In all these it should be obvious what would be the sensible default, but this: > > typeset var Both bash and zsh are consistent. Regardless of the presence or absence of a storage specifier, bash leaves the variable unset while zsh sets it to the "natural" value of the parameter's storage type. By natural I mean neutral w.r.t. +=. If `typeset -i var` was setting `var` to zero while `typeset var` was leaving it unset, that would be inconsistent. In my opinion this would be worse than the behavior of bash and zsh. The fact that unset parameters are also called "null" in ksh/bash/zsh invites confusion when comparing them to languages that can have parameters with null *values*. Those null values are first-class citizens. You can pass them as arguments to functions, store them in arrays, etc. Shells don't have null *values*, they just have unset parameters. Most languages (in fact, all languages I know) either don't have the notion of an unset variable with function scope, or automatically give all declared variables values. The closest equivalent to ksh/bash/zsh I'm aware of is elisp because it also has dynamic typing and dynamic scope. elisp has the same notion of an unset variable as ksh/bash/zsh (they are called void in elisp). You can declare local variables with `let` and unset them with `makunbound`. These behave like `typeset` and `unset` in zsh -- in order to create an unset variable with function scope, you need to declare it and then unset. Declaring the variable without value won't do. In sum, what zsh does makes sense to me and feels natural and consistent with other languages I know. That isn't to say that I consider the behavior of ksh/bash incorrect. It's a bit surprising but sensible. I could definitely get used to it. The strongest argument for changing zsh is consistency with ksh and bash. The strongest argument against it is that it'll break a lot of existing zsh code. It's not my call but to me this looks like a no-go. Roman. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 8:45 ` Roman Perepelitsa @ 2020-11-12 10:47 ` Peter Stephenson 2020-11-12 18:48 ` Bart Schaefer 2020-11-12 19:49 ` Felipe Contreras 2020-11-12 18:46 ` Felipe Contreras 1 sibling, 2 replies; 53+ messages in thread From: Peter Stephenson @ 2020-11-12 10:47 UTC (permalink / raw) To: Zsh hackers list With some trepidation, let me see if I can try and sum up. fn() { typeset foo # foo is regarded as set (in the sense "not unset") here. } Other shells would treat foo as unset at that point. This is a long standing feature of zsh, so the default behaviour is not going to change. Almost certainly there was no direct thought at the time zsh was implemented about the details of this case, so it was probably not a formal syntactical decision. It is a bug when emulating other shells (although note that there are plenty of such bugs --- emulation is never complete). I said I thought we'd done something about this, but I don't see any evidence, so I was probably wrong. There is definitely scope for improvement. Given that all shells would treat $foo as an empty string in the context above, the practical impact is limited to a few edge cases --- granted that can be infuriating (and more) when you hit one, so I am not dismissing such cases. That's why this issue doesn't often come up despite its long-standing nature. For the same reason, that $foo will reliably substitute as an empty string, I don't see any *overriding* reason for the behaviour of other shells. That absolutely doesn't mean I see no arguments for that behaviour, all of which I think have now been rehearsed. Hope that's useful. pws ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 10:47 ` Peter Stephenson @ 2020-11-12 18:48 ` Bart Schaefer 2020-11-12 19:49 ` Felipe Contreras 1 sibling, 0 replies; 53+ messages in thread From: Bart Schaefer @ 2020-11-12 18:48 UTC (permalink / raw) To: Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 975 bytes --] On Thu, Nov 12, 2020 at 2:48 AM Peter Stephenson < p.w.stephenson@ntlworld.com> wrote: > > This is a long standing feature of zsh, so the default behaviour > is not going to change. Almost certainly there was no direct > thought at the time zsh was implemented about the details > of this case, so it was probably not a formal syntactical > decision. > If we go back far enough, to the original Bourne shell, there's no such thing as local variables, no variable type except string, and no variable that can both exist and be unset. Everything is either in the exported global environment as a string, or it doesn't exist at all. The next step is variables that can exist in the global environment but are not exported. But they still always have to either be a (possibly empty) string, or not exist at all. Zsh preserves that behavior, then adds that you can explicitly unset a variable and zsh will remember its "type" as long as the variable is in the same scope. [-- Attachment #2: Type: text/html, Size: 1389 bytes --] ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 10:47 ` Peter Stephenson 2020-11-12 18:48 ` Bart Schaefer @ 2020-11-12 19:49 ` Felipe Contreras 1 sibling, 0 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-12 19:49 UTC (permalink / raw) To: Peter Stephenson; +Cc: Zsh hackers list On Thu, Nov 12, 2020 at 4:48 AM Peter Stephenson <p.w.stephenson@ntlworld.com> wrote: > > With some trepidation, let me see if I can try and sum up. > > fn() { > typeset foo > # foo is regarded as set (in the sense "not unset") here. > } > > Other shells would treat foo as unset at that point. > > This is a long standing feature of zsh It's not a bug, it's a feature! Never heard that one before. > It is a bug when emulating other shells (although note that there > are plenty of such bugs --- emulation is never complete). I > said I thought we'd done something about this, but I don't see any > evidence, so I was probably wrong. There is definitely scope for > improvement. Indeed, I've been looking at the code, and there doesn't seem to be anything similar. It's making too many assumptions about the starting state of a parameter. > Given that all shells would treat $foo as an empty string in > the context above, the practical impact is limited to a few > edge cases --- granted that can be infuriating (and more) > when you hit one, so I am not dismissing such cases. That's why > this issue doesn't often come up despite its long-standing > nature. Absence of evidence is not evidence of absence. Perhaps a considerable amount of people have hit this issue, but they haven't bothered to contact the mailing lists. Most people just make it work on their code, and move on. > For the same reason, that $foo will reliably substitute as > an empty string, I don't see any *overriding* reason for > the behaviour of other shells. That absolutely doesn't > mean I see no arguments for that behaviour, all of > which I think have now been rehearsed. There is a difference between a variable that contains an empty string, and an unset variable, this is an undeniable fact about the shell language. There is a reason why people use ${foo+set} instead of $foo when they want to check if a variable is set, as opposed to empty. The fact that most code doesn't care about the difference doesn't mean there isn't some code that does. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 8:45 ` Roman Perepelitsa 2020-11-12 10:47 ` Peter Stephenson @ 2020-11-12 18:46 ` Felipe Contreras 2020-11-12 19:10 ` Roman Perepelitsa 2020-11-12 19:26 ` Bart Schaefer 1 sibling, 2 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-12 18:46 UTC (permalink / raw) To: Roman Perepelitsa; +Cc: Zsh hackers list On Thu, Nov 12, 2020 at 2:46 AM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > On Wed, Nov 11, 2020 at 9:42 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > In all these it should be obvious what would be the sensible default, but this: > > > > typeset var > > Both bash and zsh are consistent. Regardless of the presence or > absence of a storage specifier, bash leaves the variable unset while > zsh sets it to the "natural" value of the parameter's storage type. By > natural I mean neutral w.r.t. +=. If `typeset -i var` was setting > `var` to zero while `typeset var` was leaving it unset, that would be > inconsistent. In my opinion this would be worse than the behavior of > bash and zsh. No. Zsh is not consistent. I did not type /typeset var=''/, I typed /typeset var/. > The fact that unset parameters are also called "null" in ksh/bash/zsh > invites confusion when comparing them to languages that can have > parameters with null *values*. Those null values are first-class > citizens. You can pass them as arguments to functions, store them in > arrays, etc. Shells don't have null *values*, they just have unset > parameters. This is distinction without a difference, like saying we are not lost, we just don't know where we are. Conceptually it is the same thing, you are just using a different word for it. It's wordplay. An unset variable is for all intents and purposes a variable with a null value. > Most languages (in fact, all languages I know) either don't have the > notion of an unset variable with function scope, or automatically give > all declared variables values. The closest equivalent to ksh/bash/zsh > I'm aware of is elisp because it also has dynamic typing and dynamic > scope. elisp has the same notion of an unset variable as ksh/bash/zsh > (they are called void in elisp). You can declare local variables with > `let` and unset them with `makunbound`. These behave like `typeset` > and `unset` in zsh -- in order to create an unset variable with > function scope, you need to declare it and then unset. Declaring the > variable without value won't do. So you don't know JavaScript (one of the most popular languages today)? > var v > typeof v 'undefined' Even in Python and Ruby the way you "declare" variables without a type is by setting them to the equivalent of the null value. This has *exactly* the same effect as "local x". Once again it's a distinction without a difference. In Swift you can declare a variable with the type "Any", and by default it has the nil value. Virtually all languages have a way of declaring a variable with a local scope, and *all* of them (including shell) have an idiom to do it without assigning an empty string (except zsh). > In sum, what zsh does makes sense to me and feels natural and > consistent with other languages I know. Carrying luggage without wheels also felt natural. Humans can get used to anything. You cannot tell me that if I originally have this: func () { [[ -n "$1" ]] && var=$1 dosomething ${var-other} } And I want to change the scope of the variable, so it's not set globally (which can be done in plenty of languages), and then I do this: func () { typeset var [[ -n "$1" ]] && var=$1 dosomething ${var-other} } It makes sense to *change* the behavior of the code. Can you? > That isn't to say that I > consider the behavior of ksh/bash incorrect. It's a bit surprising but > sensible. I could definitely get used to it. The strongest argument > for changing zsh is consistency with ksh and bash. The strongest > argument against it is that it'll break a lot of existing zsh code. > It's not my call but to me this looks like a no-go. This is a false dichotomy. Adding a setopt option for the new behavior doesn't break a lot of existing zsh code. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 18:46 ` Felipe Contreras @ 2020-11-12 19:10 ` Roman Perepelitsa 2020-11-12 21:08 ` Felipe Contreras 2020-11-12 19:26 ` Bart Schaefer 1 sibling, 1 reply; 53+ messages in thread From: Roman Perepelitsa @ 2020-11-12 19:10 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Thu, Nov 12, 2020 at 7:47 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > This is distinction without a difference, like saying we are not lost, > we just don't know where we are. Conceptually it is the same thing, > you are just using a different word for it. It's wordplay. > > An unset variable is for all intents and purposes a variable with a null value. Only in languages where variables cannot have null values, and only because you can declare "null" to be a synonym for "unset" in this case. > JavaScript In JavaScript you unset a variable with `delete foo` and you assign it a "null" value (in quotes because javascript has another null) with `foo = undefined`. These are not equivalent. Note that these two snippets have different effect: var foo and var foo delete foo Just line in zsh, and unlike ksh/bash. > Python Same thing but `del var` and `var = None`. Et cetera. ksh and bash are rather exceptional in this regard. Roman. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 19:10 ` Roman Perepelitsa @ 2020-11-12 21:08 ` Felipe Contreras 2020-11-13 8:51 ` Roman Perepelitsa 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-12 21:08 UTC (permalink / raw) To: Roman Perepelitsa; +Cc: Zsh hackers list On Thu, Nov 12, 2020 at 1:11 PM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > On Thu, Nov 12, 2020 at 7:47 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > This is distinction without a difference, like saying we are not lost, > > we just don't know where we are. Conceptually it is the same thing, > > you are just using a different word for it. It's wordplay. > > > > An unset variable is for all intents and purposes a variable with a null value. > > Only in languages where variables cannot have null values, and only > because you can declare "null" to be a synonym for "unset" in this > case. No. Intents and purposes don't depend on the language you cherry-pick. > > JavaScript > > In JavaScript you unset a variable with `delete foo` and you assign it > a "null" value (in quotes because javascript has another null) with > `foo = undefined`. These are not equivalent. > > Note that these two snippets have different effect: > > var foo > > and > > var foo > delete foo > > Just line in zsh, and unlike ksh/bash. No. That code doesn't even work in JavaScript: > var foo undefined > delete foo false Delete foo returns false because it didn't do anything. > var foo="test" undefined > delete foo false > foo 'test' The variable is still there with type and value. If you turn on the strict mode you get: "SyntaxError: Delete of an unqualified identifier in strict mode." The delete operator is there to handle properties of objects, not variables [1]. The closest to unset is assigning a value of "undefined". But the important thing is that foo is *never* an empty string. > > Python > > Same thing but `del var` and `var = None`. > > Et cetera. ksh and bash are rather exceptional in this regard. This is a false equivalence. You are talking about two different concepts as if they were the same thing. They are not. foo="global" func () { typeset foo unset foo foo="local" echo $foo } func echo $foo In this example unset does not do the same thing as the del statement in Python. The scope of "foo" is not changed. The equivalent of "unset foo" is "foo = None". A real equivalence is undefined in JavaScript: var foo="global"; function func() { var foo; foo = undefined; foo = "local"; console.log(foo); } func(); console.log(foo); In both cases "unset foo" and "foo = undefined" do *exactly* the same thing, which is return the variable to its original state. And in both cases if you remove "typeset foo" or "var foo" the effect is *exactly* the same; modifying foo inside the function modifies the global variable. If you compare apples to apples the equivalence is obvious. In JavaScript "var foo" does not set foo to an empty string. Cheers. [1] http://ecma-international.org/ecma-262/11.0/#sec-delete-operator -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 21:08 ` Felipe Contreras @ 2020-11-13 8:51 ` Roman Perepelitsa 2020-11-14 0:52 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Roman Perepelitsa @ 2020-11-13 8:51 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Thu, Nov 12, 2020 at 10:08 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > On Thu, Nov 12, 2020 at 1:11 PM Roman Perepelitsa > <roman.perepelitsa@gmail.com> wrote: >> > > Note that these two snippets have different effect: > > > > var foo > > > > and > > > > var foo > > delete foo > > > > Just line in zsh, and unlike ksh/bash. > > No. That code doesn't even work in JavaScript: I didn't realize you cannot unset variables in JavaScript. Then comparing it with shells isn't very useful. > "unset foo" and "foo = undefined" do *exactly* the same thing `undefined` is just a value, so `foo = undefined` simply changes the value of foo. You can still pass foo around, just like you could do it if it held any other value. Unsetting a parameter in a shell is quite different. It's impossible to detect a difference between these two cases: 1) foo was never declared, and 2) foo was declared and subsequently unset. (At least in global scope. Shells differ w.r.t. local variables.) We'll need another language that allows unsetting variables to have a meaningful comparison. How about elisp? As I mentioned earlier, it shares two important properties with ksh/bash/zsh -- dynamic typing and dynamic scope. In elisp declaring a variable and then unsetting it is not equivalent to just declaring a variable. Like in zsh and unlike ksh/bash. > In JavaScript "var foo" does not set foo to an empty string. It sets *some* value, specifically `undefined`. In shells there is no such value, so assigning `undefined` is not an option. The only options are: assign the default value that corresponds to the parameter's storage type (an empty string for string parameters) or leave the parameter unset. The latter has no equivalence in JavaScript because JavaScript has no notion of unset variables. I don't think this discussion will affect anything of substance. I'm continuing merely out of politeness. You've asked why I consider the behavior of zsh natural and I'm doing my best to explain. I can see that you consider the behavior of ksh/bash natural and I agree that your position is consistent. I'm not arguing that what zsh does is objectively *more* natural, only that it's also consistent and has precedence in other languages (elisp). I think I've found a language that has constructs equivalent to typeset and unset with the same semantics as in ksh/bash. In Lua this snippet: local x x = nil Is equivalent to this: local x Moreover, variables to which nil has been assigned are indistinguishable from variables that have never been declared. "Variable foo is nil" has the same meaning as "variable foo does not exist". Like in shells and unlike JavaScript. Roman. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-13 8:51 ` Roman Perepelitsa @ 2020-11-14 0:52 ` Felipe Contreras 2020-11-14 5:41 ` Roman Perepelitsa 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-14 0:52 UTC (permalink / raw) To: Roman Perepelitsa; +Cc: Zsh hackers list On Fri, Nov 13, 2020 at 2:52 AM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > On Thu, Nov 12, 2020 at 10:08 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > On Thu, Nov 12, 2020 at 1:11 PM Roman Perepelitsa > > <roman.perepelitsa@gmail.com> wrote: > >> > > > Note that these two snippets have different effect: > > > > > > var foo > > > > > > and > > > > > > var foo > > > delete foo > > > > > > Just line in zsh, and unlike ksh/bash. > > > > No. That code doesn't even work in JavaScript: > > I didn't realize you cannot unset variables in JavaScript. Then > comparing it with shells isn't very useful. > > > "unset foo" and "foo = undefined" do *exactly* the same thing > > `undefined` is just a value, so `foo = undefined` simply changes the > value of foo. You can still pass foo around, just like you could do it > if it held any other value. Unsetting a parameter in a shell is quite > different. It's impossible to detect a difference between these two > cases: 1) foo was never declared, and 2) foo was declared and > subsequently unset. (At least in global scope. Shells differ w.r.t. > local variables.) The two things are functionally *exactly* the same. In JavaScript if you don't declare foo, accessing it gives you the value of "undefined", and if you declare it and "unset" it, it also gives you "undefined". Exactly the same as in shell. You just don't want to accept they are functionally the same because you don't want them to be the same. > We'll need another language that allows unsetting variables to have a > meaningful comparison. How about elisp? As I mentioned earlier, it > shares two important properties with ksh/bash/zsh -- dynamic typing > and dynamic scope. In elisp declaring a variable and then unsetting it > is not equivalent to just declaring a variable. Like in zsh and unlike > ksh/bash. Lisp doesn't allow defining variables without a value. > > In JavaScript "var foo" does not set foo to an empty string. > > It sets *some* value, specifically `undefined`. In shells there is no > such value, so assigning `undefined` is not an option. Once again: a distinction without a difference. https://en.wikipedia.org/wiki/Distinction_without_a_difference > I don't think this discussion will affect anything of substance. I'm > continuing merely out of politeness. You've asked why I consider the > behavior of zsh natural and I'm doing my best to explain. Yes, but you have avoided some of my strongest arguments, for example this: func () { [[ -n "$1" ]] && var=$1 dosomething ${var-other} } func () { typeset var [[ -n "$1" ]] && var=$1 dosomething ${var-other} } You have never explained how it makes sense that adding that extra line changes the behavior. > I'm not arguing that what zsh does is > objectively *more* natural, only that it's also consistent and has > precedence in other languages (elisp). And I've shown you how you are comparing apples to oranges. > I think I've found a language that has constructs equivalent to > typeset and unset with the same semantics as in ksh/bash. In Lua this > snippet: > > local x > x = nil > > Is equivalent to this: > > local x > > Moreover, variables to which nil has been assigned are > indistinguishable from variables that have never been declared. > "Variable foo is nil" has the same meaning as "variable foo does not > exist". Like in shells and unlike JavaScript. Exactly the same thing as in JavaScript, just s/nil/undefined/. Either way, "local x" in Lua does exactly the same thing as it does in Bash. When you compare apples to apples the behavior is exactly the same in all languages. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-14 0:52 ` Felipe Contreras @ 2020-11-14 5:41 ` Roman Perepelitsa 2020-11-16 19:41 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Roman Perepelitsa @ 2020-11-14 5:41 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Sat, Nov 14, 2020 at 1:52 AM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > In JavaScript if you don't declare foo, accessing it gives you the > value of "undefined", and if you declare it and "unset" it, it also > gives you "undefined". Here's what I'm getting in Chrome console: console.log(foo) Uncaught ReferenceError: foo is not defined foo = undefined console.log(foo) undefined Is this behavior non-standard? > You just don't want to accept they are functionally the same because > you don't want them to be the same. Let's keep the discussion limited to the subject matter of programming languages. > Lisp doesn't allow defining variables without a value. Here's what I'm getting in GNU Emacs 26.3: (defun foo () (let ((var)) var)) (defun bar () (let ((var)) (makunbound 'var) var)) (foo) nil (bar) *** Eval error *** Symbol’s value as variable is void: var A variable declared without a value gets the value of nil. You can pass nil around like any other value. > you have avoided some of my strongest arguments, for example this: > > func () { > [[ -n "$1" ]] && var=$1 > dosomething ${var-other} > } > > func () { > typeset var > [[ -n "$1" ]] && var=$1 > dosomething ${var-other} > } > > You have never explained how it makes sense that adding that extra > line changes the behavior. I thought you were arguing that the behavior of `typeset var` in ksh/bash makes sense while in zsh it doesn't. However, in the example you've given above adding `typeset var` to func changes the function's behavior in all shells. What am I missing? > > Moreover, [in Lua] variables to which nil has been assigned are > > indistinguishable from variables that have never been declared. > > "Variable foo is nil" has the same meaning as "variable foo does not > > exist". Like in shells and unlike JavaScript. > > Exactly the same thing as in JavaScript, just s/nil/undefined/. If you try to print a variable that hasn't been defined, you'll get an error in JavaScript and "nil" in Lua. > Either way, "local x" in Lua does exactly the same thing as it does in Bash. That was my point. Originally I said I didn't know of any language that does what ksh/bash does but then I realized that Lua could fit the bill, so I mentioned it. To be more specific, I was looking for a language that 1) allows you to declare variables without specifying their values; 2) allows you to unset/unbind/undeclare variables; 3) the effect of declaring a variable and immediately unsetting it is equivalent to declaring a variable without specifying the initial value. FWIW, one of my gripes with Lua is that accessing an undeclared variable gives you nil. If it was an error instead (which I would prefer), Lua wouldn't satisfy the 3rd requirement I've listed above, so it wouldn't be like ksh/bash for the purpose of this discussion. It would be like zsh and elisp. > The most straightforward way is not necessarily the best way. > > Very often the best way takes effort. This is obviously true. I'll summarize my position. I believe it is in agreement with Peter and Bart but I wouldn't presume speaking for them. - The way typeset works in zsh makes sense. There is no inconsistency, there is precedence in other languages, and it was a natural evolution from global-only parameters. - If we could change history, it would be better if typeset in zsh worked the same way as in ksh/bash because that behavior also makes sense and compatibility is valuable. - It's infeasible to change the behavior of typeset in zsh in native mode because it'll break too much user code. - It's feasible and desirable to make typeset compatible with ksh/bash when KSH_TYPESET is set. Roman. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-14 5:41 ` Roman Perepelitsa @ 2020-11-16 19:41 ` Felipe Contreras 2020-11-16 20:22 ` Roman Perepelitsa 2020-11-17 20:54 ` Bart Schaefer 0 siblings, 2 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-16 19:41 UTC (permalink / raw) To: Roman Perepelitsa; +Cc: Zsh hackers list On Fri, Nov 13, 2020 at 11:41 PM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > On Sat, Nov 14, 2020 at 1:52 AM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > In JavaScript if you don't declare foo, accessing it gives you the > > value of "undefined", and if you declare it and "unset" it, it also > > gives you "undefined". > > Here's what I'm getting in Chrome console: > > console.log(foo) > > Uncaught ReferenceError: foo is not defined > > foo = undefined > console.log(foo) > > undefined > > Is this behavior non-standard? We are talking about local variables. Did you declare 'foo' as a local variable? Moreover, JavaScript has the notion of hoisted variables: console.log(foo); # undefined var foo; > > You just don't want to accept they are functionally the same because > > you don't want them to be the same. > > Let's keep the discussion limited to the subject matter of programming > languages. The interpretation of language is directly related to programming languages. You want to ignore an interpretation because it's inconvenient for you. It is a fact the two are functionally the same. > > Lisp doesn't allow defining variables without a value. > A variable declared without a value gets the value of nil. You can > pass nil around like any other value. If "(let ((var)) ...)" is the same as "(let ((var nil)) ...)", then it's *exactly* the same as "var = None" in Python. > > you have avoided some of my strongest arguments, for example this: > > > > func () { > > [[ -n "$1" ]] && var=$1 > > dosomething ${var-other} > > } > > > > func () { > > typeset var > > [[ -n "$1" ]] && var=$1 > > dosomething ${var-other} > > } > > > > You have never explained how it makes sense that adding that extra > > line changes the behavior. > > I thought you were arguing that the behavior of `typeset var` in > ksh/bash makes sense while in zsh it doesn't. However, in the example > you've given above adding `typeset var` to func changes the function's > behavior in all shells. What am I missing? It doesn't change the behavior of the function func(), it only changes the scope of the variable "var" (like in all languages). You know what the behavior of the original func() was. It seems you are being obtuse on purpose. > > > Moreover, [in Lua] variables to which nil has been assigned are > > > indistinguishable from variables that have never been declared. > > > "Variable foo is nil" has the same meaning as "variable foo does not > > > exist". Like in shells and unlike JavaScript. > > > > Exactly the same thing as in JavaScript, just s/nil/undefined/. > > If you try to print a variable that hasn't been defined, you'll get an > error in JavaScript and "nil" in Lua. Declared is not the same as defined. func () { var foo; } Foo is undefined, but declared with a local scope. > > Either way, "local x" in Lua does exactly the same thing as it does in Bash. > > That was my point. Originally I said I didn't know of any language > that does what ksh/bash does but then I realized that Lua could fit > the bill, so I mentioned it. To be more specific, I was looking for a > language that 1) allows you to declare variables without specifying > their values; 2) allows you to unset/unbind/undeclare variables; 3) > the effect of declaring a variable and immediately unsetting it is > equivalent to declaring a variable without specifying the initial > value. 1) But you ignore the languages that can use nil, which is functionally the same as no-value. 2) But you ignore the languages that can unset the value of a variable (using nil), which is functionally the same as no-value. 3) Which makunbound doesn't do in elisp (and var=nil does do on virtually all languages). > FWIW, one of my gripes with Lua is that accessing an undeclared > variable gives you nil. If it was an error instead (which I would > prefer), Lua wouldn't satisfy the 3rd requirement I've listed above, > so it wouldn't be like ksh/bash for the purpose of this discussion. It > would be like zsh and elisp. It does satisfy 3), you just do want to accept it. local foo print(foo) Is *exactly* the same as: local foo foo = nil -- unset print(foo) All languages we explored have the same notion (inside a function): JavaScript: var foo; console.log(foo); # undefined foo = 'set'; foo = undefined' # unset() console.log(foo); # undefined Python: foo = None print(foo) # None foo = "set" foo = None # unset() print(foo) # None Ruby: foo = nil p foo # nil foo = "set" foo = nil # unset() p foo # nil Lua: local foo print(foo) # nil foo = 'set' foo = nil # unset() print(foo) # nil Emacs Lisp: (defun foo () (let ((var)) (print var) ; nil (set 'var "set") (set 'var nil) ; unset (print var) ; nil ) ) Shell: local foo echo ${foo-nil} # nil foo="set" unset foo echo ${foo-nil} # nil These are all functionally *exactly* the same. And that's an undeniable fact. > > The most straightforward way is not necessarily the best way. > > > > Very often the best way takes effort. > > This is obviously true. > > I'll summarize my position. I believe it is in agreement with Peter > and Bart but I wouldn't presume speaking for them. > > - The way typeset works in zsh makes sense. There is no inconsistency, > there is precedence in other languages, and it was a natural evolution > from global-only parameters. That is an opinion. I disagree. > - If we could change history, it would be better if typeset in zsh > worked the same way as in ksh/bash because that behavior also makes > sense and compatibility is valuable. Indeed. > - It's infeasible to change the behavior of typeset in zsh in native > mode because it'll break too much user code. Nothing is impossible. It's just harder when you don't even think of trying it. > - It's feasible and desirable to make typeset compatible with ksh/bash > when KSH_TYPESET is set. KSH_TYPESET does something else that not even ksh does. But another option might make sense. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-16 19:41 ` Felipe Contreras @ 2020-11-16 20:22 ` Roman Perepelitsa 2020-11-17 20:28 ` Felipe Contreras 2020-11-17 20:54 ` Bart Schaefer 1 sibling, 1 reply; 53+ messages in thread From: Roman Perepelitsa @ 2020-11-16 20:22 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list Felipe, you are doubling down on targeting *me* in your statements despite my prior request to keep the discussion focused on programming languages. The discussion is going nowhere, so I suggest that we drop it. Roman. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-16 20:22 ` Roman Perepelitsa @ 2020-11-17 20:28 ` Felipe Contreras 2020-11-18 22:45 ` Daniel Shahaf 2020-11-19 2:59 ` Bart Schaefer 0 siblings, 2 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-17 20:28 UTC (permalink / raw) To: Roman Perepelitsa; +Cc: Zsh hackers list On Mon, Nov 16, 2020 at 2:22 PM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > Felipe, you are doubling down on targeting *me* in your statements > despite my prior request to keep the discussion focused on programming > languages. I am not targeting you. I am making factual objective statements: 1. A and B are functionally the same 2. You don't want to accept that A and B are functionally the same It is 100% a fact that A and B are functionally the same, and it is also a fact that you don't accept this fact. The only reason the discussion is going nowhere is that you don't want to accept this true fact, but that doesn't stop it from being a fact. Curiously, you are also not denying the fact either, you are simply ignoring it. Every time I say A and B are *functionally* the same, you ignore that claim. If you don't at least attempt to engage with that fact (which I tried to exemplify in dozens of ways already), then I agree; we can't move forward. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-17 20:28 ` Felipe Contreras @ 2020-11-18 22:45 ` Daniel Shahaf 2020-11-22 1:20 ` Felipe Contreras 2020-11-19 2:59 ` Bart Schaefer 1 sibling, 1 reply; 53+ messages in thread From: Daniel Shahaf @ 2020-11-18 22:45 UTC (permalink / raw) To: Felipe Contreras; +Cc: Roman Perepelitsa, Zsh hackers list Felipe Contreras wrote on Tue, 17 Nov 2020 14:28 -0600: > On Mon, Nov 16, 2020 at 2:22 PM Roman Perepelitsa > <roman.perepelitsa@gmail.com> wrote: > > > > Felipe, you are doubling down on targeting *me* in your statements > > despite my prior request to keep the discussion focused on programming > > languages. > > I am not targeting you. I am making factual objective statements: > > 1. A and B are functionally the same > 2. You don't want to accept that A and B are functionally the same > > It is 100% a fact that A and B are functionally the same, and it is > also a fact that you don't accept this fact. > > The only reason the discussion is going nowhere is that you don't want > to accept this true fact, but that doesn't stop it from being a fact. > > Curiously, you are also not denying the fact either, you are simply > ignoring it. Every time I say A and B are *functionally* the same, you > ignore that claim. > > If you don't at least attempt to engage with that fact (which I tried > to exemplify in dozens of ways already), then I agree; we can't move > forward. Do not argue about a person. Argue about the technical matter at hand. What are A and B? Why does the Python example not use «del» as the "unset" operation? ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-18 22:45 ` Daniel Shahaf @ 2020-11-22 1:20 ` Felipe Contreras 2020-11-23 4:00 ` Daniel Shahaf 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-22 1:20 UTC (permalink / raw) To: Daniel Shahaf; +Cc: Roman Perepelitsa, Zsh hackers list On Wed, Nov 18, 2020 at 4:45 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > Do not argue about a person. Argue about the technical matter at hand. That's what I did. The technical matter was being ignored. > What are A and B? I already explained this multiple times: A: unset foo B: foo = nil > Why does the Python example not use «del» as the "unset" operation? Because it doesn't do the same thing as unset. In shell, this leaves foo declared in a local scope: local foo # declare unset foo # unset In Python, this doesn't: foo = None # declare del foo # undeclare They are *not* functionally the same thing. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-22 1:20 ` Felipe Contreras @ 2020-11-23 4:00 ` Daniel Shahaf 2020-11-23 6:18 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Daniel Shahaf @ 2020-11-23 4:00 UTC (permalink / raw) To: Felipe Contreras; +Cc: Roman Perepelitsa, Zsh hackers list Felipe Contreras wrote on Sat, Nov 21, 2020 at 19:20:56 -0600: > On Wed, Nov 18, 2020 at 4:45 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > > Do not argue about a person. Argue about the technical matter at hand. > > That's what I did. The technical matter was being ignored. > > > What are A and B? > > I already explained this multiple times: > > A: unset foo > B: foo = nil And in Python, A is «del foo»; B is «foo = None»; and they aren't equivalent. Actually, more precisely, Python doesn't even *have* a B, because Python doesn't have a syntax for declaring a variable without a value. (When you write «foo = None», that «None» is not implicitly provided by the language.) However, I don't see how any of this is an argument in favour of the behaviour change you proposed. Other languages' behaviours be what they may, they're unlikely to be a good enough reason to break backwards compatibility. (For instance, I don't think a proposal to disable null elision would be accepted, due to backwards compatibility concerns, regardless of how few other languages do null elision.) > > Why does the Python example not use «del» as the "unset" operation? > > Because it doesn't do the same thing as unset. > > In shell, this leaves foo declared in a local scope: > > local foo # declare > unset foo # unset > > In Python, this doesn't: > > foo = None # declare > del foo # undeclare > > They are *not* functionally the same thing. In Python, the "declare" operation would be just «pass», or more precisely, the removal of any «global foo» declarations… but, again, unless this Python discussion somehow bears on a proposed change to zsh, I'm not interested in continuing it. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-23 4:00 ` Daniel Shahaf @ 2020-11-23 6:18 ` Felipe Contreras 0 siblings, 0 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-23 6:18 UTC (permalink / raw) To: Daniel Shahaf; +Cc: Roman Perepelitsa, Zsh hackers list On Sun, Nov 22, 2020 at 10:00 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > Felipe Contreras wrote on Sat, Nov 21, 2020 at 19:20:56 -0600: > > On Wed, Nov 18, 2020 at 4:45 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > > > > Do not argue about a person. Argue about the technical matter at hand. > > > > That's what I did. The technical matter was being ignored. > > > > > What are A and B? > > > > I already explained this multiple times: > > > > A: unset foo > > B: foo = nil > > And in Python, A is «del foo»; B is «foo = None»; and they aren't > equivalent. Actually, more precisely, Python doesn't even *have* a B, > because Python doesn't have a syntax for declaring a variable without > a value. (When you write «foo = None», that «None» is not implicitly > provided by the language.) Are your A and B functionally the same? No. Are my A and B functionally the same? Yes. Those are undeniable facts. > However, I don't see how any of this is an argument in favour of the > behaviour change you proposed. Other languages' behaviours be what they > may, they're unlikely to be a good enough reason to break backwards > compatibility. (For instance, I don't think a proposal to disable null > elision would be accepted, due to backwards compatibility concerns, > regardless of how few other languages do null elision.) I made the claim and I've substantiated it. Others disagreed with the claim, and argued against it. If you don't see how the fact that virtually all languages do the same thing as Bash and ksh is relevant, then don't argue against the claim. But my claim still stands. > > > Why does the Python example not use «del» as the "unset" operation? > > > > Because it doesn't do the same thing as unset. > > > > In shell, this leaves foo declared in a local scope: > > > > local foo # declare > > unset foo # unset > > > > In Python, this doesn't: > > > > foo = None # declare > > del foo # undeclare > > > > They are *not* functionally the same thing. > > In Python, the "declare" operation would be just «pass», or more > precisely, the removal of any «global foo» declarations… but, again, > unless this Python discussion somehow bears on a proposed change to zsh, > I'm not interested in continuing it. No. That's not how you declare local variables in Python. If you are not interested in continuing it then don't argue against it. Either argue against my claim or don't, but you can't have your cake and eat it too. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-17 20:28 ` Felipe Contreras 2020-11-18 22:45 ` Daniel Shahaf @ 2020-11-19 2:59 ` Bart Schaefer 2020-11-22 1:50 ` Felipe Contreras 1 sibling, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-19 2:59 UTC (permalink / raw) To: Felipe Contreras; +Cc: Roman Perepelitsa, Zsh hackers list On Tue, Nov 17, 2020 at 12:28 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > It is 100% a fact that A and B are functionally the same, and it is > also a fact that you don't accept this fact. What has not yet been accepted is your proof of this "fact." It is 100% your assertion that A and B are functionally the same, but as I've noted, you're using behavior of languages that have a first-class value of "undefined" to assert something about a language where there is no such first-class value. Your premise that zsh's default behavior is not internally consistent is based on that assertion. I'm curious to see your proof, but it's unlikely to convince anyone who currently disagrees with you to undertake alteration of the default behavior. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-19 2:59 ` Bart Schaefer @ 2020-11-22 1:50 ` Felipe Contreras 0 siblings, 0 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-22 1:50 UTC (permalink / raw) To: Bart Schaefer; +Cc: Roman Perepelitsa, Zsh hackers list On Wed, Nov 18, 2020 at 8:59 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > On Tue, Nov 17, 2020 at 12:28 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > It is 100% a fact that A and B are functionally the same, and it is > > also a fact that you don't accept this fact. > > What has not yet been accepted is your proof of this "fact." It is > 100% your assertion that A and B are functionally the same, but as > I've noted, you're using behavior of languages that have a first-class > value of "undefined" to assert something about a language where there > is no such first-class value. So? The behavior is still *functionally* the same. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-16 19:41 ` Felipe Contreras 2020-11-16 20:22 ` Roman Perepelitsa @ 2020-11-17 20:54 ` Bart Schaefer 2020-11-22 1:49 ` Felipe Contreras 1 sibling, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-17 20:54 UTC (permalink / raw) To: Felipe Contreras; +Cc: Roman Perepelitsa, Zsh hackers list On Mon, Nov 16, 2020 at 11:42 AM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > Declared is not the same as defined. True, but in the shell language traditionally the only way to declare a variable was to define it. The exception was "export VAR" which has so far been out of scope (ha ha) for this discussion, and later "readonly VAR" which has limited use if VAR is not also defined. > All languages we explored have the same notion (inside a function): I'm just going to excerpt one of these because you claim they're all the same ... > Python: > > foo = None > print(foo) # None > foo = "set" > foo = None # unset() > print(foo) # None > > Shell: > > local foo > echo ${foo-nil} # nil > foo="set" > unset foo > echo ${foo-nil} # nil > > These are all functionally *exactly* the same. And that's an undeniable fact. Except your examples are NOT the same. Your shell example introduces what amounts to a ternary test. In shell local foo echo -n $foo does not output "nil" or "undefined" or "None", it outputs NOTHING. When you throw in ${foo-nil} you're effectively writing (pseudo code) if the variable foo has no value then substitute nil else substitute the value of foo fi There literally is no concept of "not defined" in the shell language outside of that implicit ternary; undefined is not a first-class value. You cannot write "if [[ $foo == undefined ]]" or any of the similar comparisons that can be done in most if not all of the other languages you assert are equivalent. You can use $anydamnthing in the shell anywhere an empty string can be used, without producing a null dereference or similar error -- unless of course you've activated NO_UNSET, which by the way: nounset_error() { setopt localoptions nounset print $foo # error } nounset_ok() { setopt localoptions nounset typeset foo print $foo # not error } So the decisions made about the behavior of typeset have ramifications beyond your use case. > > > The most straightforward way is not necessarily the best way. And the perfect is often the enemy of the good. Let's stop throwing aphorisms at each other, especially when they can't change decisions made decades ago. > KSH_TYPESET does something else that not even ksh does. But another > option might make sense. Which particular something are you thinking of? ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-17 20:54 ` Bart Schaefer @ 2020-11-22 1:49 ` Felipe Contreras 2020-11-23 6:48 ` Bart Schaefer 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-22 1:49 UTC (permalink / raw) To: Bart Schaefer; +Cc: Roman Perepelitsa, Zsh hackers list On Tue, Nov 17, 2020 at 2:54 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > On Mon, Nov 16, 2020 at 11:42 AM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > Python: > > > > foo = None > > print(foo) # None > > foo = "set" > > foo = None # unset() > > print(foo) # None > > > > Shell: > > > > local foo > > echo ${foo-nil} # nil > > foo="set" > > unset foo > > echo ${foo-nil} # nil > > > > These are all functionally *exactly* the same. And that's an undeniable fact. > > Except your examples are NOT the same. Your shell example introduces > what amounts to a ternary test. In shell > > local foo > echo -n $foo > > does not output "nil" or "undefined" or "None", it outputs NOTHING. > When you throw in ${foo-nil} you're effectively writing (pseudo code) > > if the variable foo has no value > then substitute nil > else substitute the value of foo > fi So? Is it *functionally* the same or not? > There literally is no concept of "not defined" in the shell language > outside of that implicit ternary; undefined is not a first-class > value. You cannot write "if [[ $foo == undefined ]]" or any of the > similar comparisons that can be done in most if not all of the other > languages you assert are equivalent. You can use $anydamnthing in the > shell anywhere an empty string can be used, without producing a null > dereference or similar error -- unless of course you've activated > NO_UNSET, which by the way: This is a smoke screen. Notions don't change the behavior of the code above. It either is *functionally* the same, or it isn't. > > > > The most straightforward way is not necessarily the best way. > > And the perfect is often the enemy of the good. Let's stop throwing > aphorisms at each other, especially when they can't change decisions > made decades ago. My statement was not an aphorism, but even if it was; that doesn't change the fact that it's true. I was not the one that brought history into the thread. You are the one that brought the history, which by definition cannot be changed. If now you are saying there's no point in talking about something that can't be changed (the past), then fine by me. > > KSH_TYPESET does something else that not even ksh does. But another > > option might make sense. > > Which particular something are you thinking of? My understanding of that option is that it changed the behavior of this: typeset var=$(echo one word) To this: builtin typeset var=$(echo one word) In other words: typeset var=one word But that's not what ksh does, at least the version I have installed. Anyway, I see now that it's obsolete, so in theory it could be reused. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-22 1:49 ` Felipe Contreras @ 2020-11-23 6:48 ` Bart Schaefer 2020-11-23 7:26 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-23 6:48 UTC (permalink / raw) To: Felipe Contreras; +Cc: Roman Perepelitsa, Zsh hackers list On Sat, Nov 21, 2020 at 5:49 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > On Tue, Nov 17, 2020 at 2:54 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > > > There literally is no concept of "not defined" in the shell language > > outside of that implicit ternary; undefined is not a first-class > > value. > > This is a smoke screen. This statement confuses me. If you are insinuating that I'm raising a point solely for the purpose of obfuscating the discussion, then either (a) you haven't been paying attention to anything I've written on this mailing list in the past 25 years, or (b) I'm forced to believe you're actively attempting to be insulting. > It either is *functionally* the same, or it isn't. You keep "shouting" that word as if saying it louder is all that's necessary. > I was not the one that brought history into the thread. You are the > one that brought the history, which by definition cannot be changed. You asked why zsh's default behavior is what it is; the answer is historical practice. Unless I've misunderstood something, the subsequent discussion has focused on the idea that we should change the default, despite that breaking several precedents, because the default behavior is not internally consistent, and that the reason it's not consistent is because of the notion that unsetting a variable is equivalent to assigning it an undefined value. Even if we grant the latter, which I don't think everyone does, it still doesn't follow that the only consistent choice for the default state of a declared variable is unset. > My understanding of [KSH_TYPESET] is that it changed the behavior of this: > > typeset var=$(echo one word) > > To this: > > builtin typeset var=$(echo one word) No; it changes the former to something closer to typeset var="$(echo one word)" because *without* the option, it was interpreted as > typeset var=one word ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-23 6:48 ` Bart Schaefer @ 2020-11-23 7:26 ` Felipe Contreras 2020-11-23 20:26 ` Bart Schaefer 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-23 7:26 UTC (permalink / raw) To: Bart Schaefer; +Cc: Roman Perepelitsa, Zsh hackers list On Mon, Nov 23, 2020 at 12:48 AM Bart Schaefer <schaefer@brasslantern.com> wrote: > > On Sat, Nov 21, 2020 at 5:49 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > On Tue, Nov 17, 2020 at 2:54 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > > > > > There literally is no concept of "not defined" in the shell language > > > outside of that implicit ternary; undefined is not a first-class > > > value. > > > > This is a smoke screen. > > This statement confuses me. If you are insinuating that I'm raising > a point solely for the purpose of obfuscating the discussion, then > either (a) you haven't been paying attention to anything I've written > on this mailing list in the past 25 years, or (b) I'm forced to > believe you're actively attempting to be insulting. No. A smoke screen screen doesn't have to be intentional. I am saying X doesn't have anything to do with Y. You are arguing Y, IMO all that is doing is diverting attention from X. > > It either is *functionally* the same, or it isn't. > > You keep "shouting" that word as if saying it louder is all that's necessary. Nope. I demonstrated how they are functionally the same with plenty of examples. > > I was not the one that brought history into the thread. You are the > > one that brought the history, which by definition cannot be changed. > > You asked why zsh's default behavior is what it is; the answer is > historical practice. Indeed, and that's all that was needed to answer *that* particular question. But then you used an historic argument to counter my claim that Zsh was not consistent. Go look at mid [1] (I don't know how you link to the archives, which don't seem to be updated). This is an entirely different matter. > Unless I've misunderstood something, the subsequent discussion has > focused on the idea that we should change the default, despite that > breaking several precedents, because the default behavior is not > internally consistent, and that the reason it's not consistent is > because of the notion that unsetting a variable is equivalent to > assigning it an undefined value. No. Again, go back to mid [1]. I specifically said: "Adding a setopt option for the new behavior doesn't break a lot of existing zsh code." I argued it makes sense to add a setopt option that turns on the behavior that a) in my opinion is more consistent, b) is what Bash and ksh does, and c) is the equivalent of what virtually all languages do. > Even if we grant the latter, which I don't think everyone does, it > still doesn't follow that the only consistent choice for the default > state of a declared variable is unset. But it does follow. I already presented several arguments, most of which have not been even addressed at all. Would like me to list them all in a document so it's clear how they have not been addressed? > > My understanding of [KSH_TYPESET] is that it changed the behavior of this: > > > > typeset var=$(echo one word) > > > > To this: > > > > builtin typeset var=$(echo one word) > > No; it changes the former to something closer to > > typeset var="$(echo one word)" > > because *without* the option, it was interpreted as > > > typeset var=one word OK. So it's the other way around. But this actually sets a precedent for an option that turns on behavior similar to that of ksh, that eventually becomes the default, because presumably it eventually made sense. The same could happen in this case... Eventually. Either way, I don't see any argument against adding an option (or reusing) to turn on this behavior. Cheers. [1] CAH+w=7ZwyKq_RxM_RXWu42Y-RbCkRtrLTqesfqCmFNc_C_CwoA@mail.gmail.com -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-23 7:26 ` Felipe Contreras @ 2020-11-23 20:26 ` Bart Schaefer 2020-11-23 23:39 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-23 20:26 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Sun, Nov 22, 2020 at 11:27 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > Nope. I demonstrated how they are functionally the same with plenty of examples. All of your examples are from other languages. > But then you used an historic argument to counter my claim that Zsh > was not consistent. The historic reference was for context. The actual argument is that zsh is consistent because the behavior of variables inside function scope mirrors that of variables at global scope. History is merely why variables behave that way at global scope. Your argument is that zsh was wrong to adopt that interpretation of variables in function scope. That doesn't make it (internally) inconsistent, it just makes it different. But there are plenty of other ways that the shell language is different from pretty much any other language you can name. Korn has spent years and many revisions gradually dragging in concepts from other languages. Zsh has so far (often just for lack of developer time/attention) not attempted to track with all of those. However ... > I argued it makes sense to add a setopt option that turns on the > behavior that a) in my opinion is more consistent, b) is what Bash and > ksh does, and c) is the equivalent of what virtually all languages do. That's where we could have been ten days ago, but you said (of changing the default) ... "Nothing is impossible. It's just harder when you don't even think of trying it." ... so we've been down the rabbit hole of arguing necessary/desirable. To hopefully tie this off, does anyone want to argue for a new option instead of adding this to KSH_TYPESET? ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-23 20:26 ` Bart Schaefer @ 2020-11-23 23:39 ` Felipe Contreras 2020-11-24 0:52 ` Bart Schaefer 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-23 23:39 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list On Mon, Nov 23, 2020 at 2:26 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > On Sun, Nov 22, 2020 at 11:27 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > Nope. I demonstrated how they are functionally the same with plenty of examples. > > All of your examples are from other languages. "It" in this case is code from Python compared with code from shell which is functionally the same, that is to say: it does the same thing. Of course it's from other languages. That's precisely what is being compared. > > But then you used an historic argument to counter my claim that Zsh > > was not consistent. > > The historic reference was for context. The actual argument is that > zsh is consistent because the behavior of variables inside function > scope mirrors that of variables at global scope. History is merely > why variables behave that way at global scope. You used history to explain what was the most straightforward way to implement the new feature without much architectural changes in zsh. This does not imply it was the best way to do it, nor does it show it is consistent from the user's point of view, because it's 100% dependent on the implementation of the shell. > Your argument is that zsh was wrong to adopt that interpretation of > variables in function scope. That doesn't make it (internally) > inconsistent, it just makes it different. I did not argue it was internally inconsistent. I grant you--after looking at the code--the change was likely internally consistent. My argument is about the consistency from user's perspective. This is the example I gave to Roman, which went completely unresponded: func () { [[ -n "$1" ]] && var=$1 dosomething ${var-other} } func () { typeset var [[ -n "$1" ]] && var=$1 dosomething ${var-other} } > > I argued it makes sense to add a setopt option that turns on the > > behavior that a) in my opinion is more consistent, b) is what Bash and > > ksh does, and c) is the equivalent of what virtually all languages do. > > That's where we could have been ten days ago, but you said (of > changing the default) ... > > "Nothing is impossible. It's just harder when you don't even think of > trying it." Yes, that was in response to you saying it was infeasible to change the default. I argued that nothing is impossible. It may be infeasible in the final analysis, but maybe not, the only way we could know is if it's tried first (with an option). So it's perfectly consistent to argue both: a) a setopt option makes sense now, and b) eventually this option can be considered to be the default and it's not necessarily completely infeasible. > ... so we've been down the rabbit hole of arguing necessary/desirable. > > To hopefully tie this off, does anyone want to argue for a new option > instead of adding this to KSH_TYPESET? Not me. I'd say any way to enable this mode would be fine, and if there's no conflict with KSH_TYPESET, that sounds like a sensible option. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-23 23:39 ` Felipe Contreras @ 2020-11-24 0:52 ` Bart Schaefer 2020-11-25 8:46 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-24 0:52 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list On Mon, Nov 23, 2020 at 3:39 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > My argument is about the consistency from user's perspective. Consistent from what user's point of view? One coming to zsh from other languages or one long familiar with zsh? Because zsh development has consistently (ahem) sided with the latter. > This is the example I gave to Roman, which went completely unresponded: > > func () { > [[ -n "$1" ]] && var=$1 > dosomething ${var-other} > } > > func () { > typeset var > [[ -n "$1" ]] && var=$1 > dosomething ${var-other} > } In the first case, $var is a global, so the behavior of ${var-other} is unknown. It's not possible to write deterministic code. In the second case, there's a knowable behavior of ${var-other}. That behavior doesn't match your expectation, but it's well-defined. To make the first function deterministic, it is necessary to write: func () { unset var [[ -n "$1" ]] && var=$1 dosomething ${var-other} } Whether one should expect "typeset var" to imply "unset" is how we ended up in this discussion. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-24 0:52 ` Bart Schaefer @ 2020-11-25 8:46 ` Felipe Contreras 2020-11-27 15:44 ` Daniel Shahaf 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-25 8:46 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list On Mon, Nov 23, 2020 at 6:52 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > On Mon, Nov 23, 2020 at 3:39 PM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > My argument is about the consistency from user's perspective. > > Consistent from what user's point of view? Any user. > One coming to zsh from > other languages or one long familiar with zsh? Because zsh > development has consistently (ahem) sided with the latter. Users can get accustomed to inconsistent behavior. The fact that some users have become accustomed to X doesn't mean X is consistent. > > This is the example I gave to Roman, which went completely unresponded: > > > > func () { > > [[ -n "$1" ]] && var=$1 > > dosomething ${var-other} > > } > > > > func () { > > typeset var > > [[ -n "$1" ]] && var=$1 > > dosomething ${var-other} > > } > > In the first case, $var is a global, so the behavior of ${var-other} > is unknown. It's not possible to write deterministic code. You are looking at the half of the picture that is irrelevant. The behavior of "func foobar" is deterministic, and you know what it will do. > In the second case, there's a knowable behavior of ${var-other}. That > behavior doesn't match your expectation, but it's well-defined. Nobody is saying it's not well-defined, we are talking about *consistency*. Only *one* change was added to B, and the behavior changed in *two* ways. > To make the first function deterministic, it is necessary to write: > > func () { > unset var > [[ -n "$1" ]] && var=$1 > dosomething ${var-other} > } > > Whether one should expect "typeset var" to imply "unset" is how we > ended up in this discussion. The only difference from A to B is that B has a line that says "declare 'var' as a local variable". That's a fact. And the behavior of the function changes in two ways (other than what was told to do). That's also a fact. It is a fact that the code is doing more than what it was told to do. If you have an operator called "declare_local_variable", and you do this: declare_local_variable var You run the code, and you find that declare_local_variable does indeed declare a local variable, but it *also* sets your cat on fire. You investigate, and you find out the documentation clearly states that declare_local_variable sets your cat on fire, so the behavior is "well-defined". But it's not what it says on the tin. Any normal person would expect such behavior to be enabled by: declare_local_variable var set_cat_on_fire And not have to type: delcare_local_variable_but_dont_set_cat_on_fire var Or worse: declare_local_variable var put_out_fire_from_cat It doesn't matter how well explained it is in the documentation, or how many people are accustomed to this behavior, it's still doing *more* than one thing. Now, you can call the fact that it's changing the behavior in more than one way any way you want. When most operators in most languages do one thing--and one thing only--and this operator does *two* things, I call that inconsistent. Maybe there's a better way to describe this fact. Maybe Git's notion of logically separate changes [1] helps (e.g. you should not mix whitespace cleanups with functional changes). But the fact is that in virtually all languages (and bash and ksh) there's an idiom to declare a local variable and *only* declare a local variable (not do anything else). Can we at least agree on that? In zsh typeset does *two* things. Cheers. [1] https://git-scm.com/docs/SubmittingPatches -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-25 8:46 ` Felipe Contreras @ 2020-11-27 15:44 ` Daniel Shahaf 2020-11-27 20:49 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Daniel Shahaf @ 2020-11-27 15:44 UTC (permalink / raw) To: Felipe Contreras; +Cc: Bart Schaefer, Zsh hackers list Felipe Contreras wrote on Wed, Nov 25, 2020 at 02:46:40 -0600: > Maybe there's a better way to describe this fact. Maybe Git's notion > of logically separate changes [1] helps (e.g. you should not mix > whitespace cleanups with functional changes). But the fact is that in > virtually all languages (and bash and ksh) there's an idiom to declare > a local variable and *only* declare a local variable (not do anything > else). > > Can we at least agree on that? In zsh typeset does *two* things. I'd rather say that «typeset» does one thing — it ${verb}s a variable (for some value of $verb) — and the zsh data model doesn't feature a "Not really a value" value, so the variable necessarily gets _some_ value, like «int foo;» in C. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-27 15:44 ` Daniel Shahaf @ 2020-11-27 20:49 ` Felipe Contreras 2020-11-27 20:59 ` Daniel Shahaf 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-27 20:49 UTC (permalink / raw) To: Daniel Shahaf; +Cc: Bart Schaefer, Zsh hackers list On Fri, Nov 27, 2020 at 9:44 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > Felipe Contreras wrote on Wed, Nov 25, 2020 at 02:46:40 -0600: > > Maybe there's a better way to describe this fact. Maybe Git's notion > > of logically separate changes [1] helps (e.g. you should not mix > > whitespace cleanups with functional changes). But the fact is that in > > virtually all languages (and bash and ksh) there's an idiom to declare > > a local variable and *only* declare a local variable (not do anything > > else). > > > > Can we at least agree on that? In zsh typeset does *two* things. > > I'd rather say that «typeset» does one thing — it ${verb}s a variable > (for some value of $verb) — and the zsh data model doesn't feature > a "Not really a value" value, so the variable necessarily gets _some_ > value, like «int foo;» in C. If it's really one thing, then why does adding it in the example above changes the behavior in *two* ways? func () { [[ -n "$1" ]] && var=$1 dosomething ${var-other} } func () { typeset var [[ -n "$1" ]] && var=$1 dosomething ${var-other} } -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-27 20:49 ` Felipe Contreras @ 2020-11-27 20:59 ` Daniel Shahaf 2020-11-27 21:33 ` Bart Schaefer 0 siblings, 1 reply; 53+ messages in thread From: Daniel Shahaf @ 2020-11-27 20:59 UTC (permalink / raw) To: Felipe Contreras; +Cc: Zsh hackers list Felipe Contreras wrote on Fri, 27 Nov 2020 20:49 +00:00: > On Fri, Nov 27, 2020 at 9:44 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > > > Felipe Contreras wrote on Wed, Nov 25, 2020 at 02:46:40 -0600: > > > Maybe there's a better way to describe this fact. Maybe Git's notion > > > of logically separate changes [1] helps (e.g. you should not mix > > > whitespace cleanups with functional changes). But the fact is that in > > > virtually all languages (and bash and ksh) there's an idiom to declare > > > a local variable and *only* declare a local variable (not do anything > > > else). > > > > > > Can we at least agree on that? In zsh typeset does *two* things. > > > > I'd rather say that «typeset» does one thing — it ${verb}s a variable > > (for some value of $verb) — and the zsh data model doesn't feature > > a "Not really a value" value, so the variable necessarily gets _some_ > > value, like «int foo;» in C. > > If it's really one thing, then why does adding it in the example above > changes the behavior in *two* ways? What two ways? > func () { > [[ -n "$1" ]] && var=$1 > dosomething ${var-other} > } > > func () { > typeset var > [[ -n "$1" ]] && var=$1 > dosomething ${var-other} > } > > -- > Felipe Contreras > ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-27 20:59 ` Daniel Shahaf @ 2020-11-27 21:33 ` Bart Schaefer 2020-11-27 23:37 ` Daniel Shahaf 0 siblings, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-27 21:33 UTC (permalink / raw) To: Daniel Shahaf; +Cc: Felipe Contreras, Zsh hackers list On Fri, Nov 27, 2020 at 1:00 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > What two ways? 1) makes var a local name 2) changes the result of ${var-other} ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-27 21:33 ` Bart Schaefer @ 2020-11-27 23:37 ` Daniel Shahaf 2020-11-27 23:45 ` Bart Schaefer 2020-11-28 0:24 ` Bart Schaefer 0 siblings, 2 replies; 53+ messages in thread From: Daniel Shahaf @ 2020-11-27 23:37 UTC (permalink / raw) To: Bart Schaefer; +Cc: Felipe Contreras, Zsh hackers list Bart Schaefer wrote on Fri, 27 Nov 2020 21:33 +00:00: > On Fri, Nov 27, 2020 at 1:00 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > > > What two ways? > > 1) makes var a local name > 2) changes the result of ${var-other} See the third hunk of workers/47576 in combination with my last answer. The best way to move forward would be to write a patch against the Test/ directory that specifies the proposed behaviour. Use the "f" flag so all newly-added tests will run, rather than just the first. Daniel ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-27 23:37 ` Daniel Shahaf @ 2020-11-27 23:45 ` Bart Schaefer 2020-11-28 0:24 ` Bart Schaefer 1 sibling, 0 replies; 53+ messages in thread From: Bart Schaefer @ 2020-11-27 23:45 UTC (permalink / raw) To: Daniel Shahaf; +Cc: Felipe Contreras, Zsh hackers list On Fri, Nov 27, 2020 at 3:38 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > Bart Schaefer wrote on Fri, 27 Nov 2020 21:33 +00:00: > > On Fri, Nov 27, 2020 at 1:00 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > > > > > What two ways? > > > > 1) makes var a local name > > 2) changes the result of ${var-other} > > See the third hunk of workers/47576 in combination with my last answer. > > The best way to move forward would be to write a patch against the Test/ > directory that specifies the proposed behaviour. Use the "f" flag so > all newly-added tests will run, rather than just the first. > > Daniel ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-27 23:37 ` Daniel Shahaf 2020-11-27 23:45 ` Bart Schaefer @ 2020-11-28 0:24 ` Bart Schaefer 2020-11-28 7:32 ` Bart Schaefer 2020-11-28 12:05 ` Felipe Contreras 1 sibling, 2 replies; 53+ messages in thread From: Bart Schaefer @ 2020-11-28 0:24 UTC (permalink / raw) To: Daniel Shahaf; +Cc: Zsh hackers list [Apparently when I tried to go look at another message, a blank reply got sent off.] On Fri, Nov 27, 2020 at 3:38 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > The best way to move forward would be to write a patch against the Test/ > directory that specifies the proposed behaviour. Use the "f" flag so > all newly-added tests will run, rather than just the first. There are existing tests that specifically check for the current behavior, so it's not as if this were simply overlooked. To write the proposed new test cases, we need to decide (this list may not be all-inclusive): whether this is going to be attached to an option (and which one, now that Oliver to at least some extent disagrees with KSH_TYPESET) or is controlled by emulation mode; what happens to "setopt NO_UNSET"; what "typeset -p" outputs following "unset".; what happens when each (any) of the EFHLRTZilu options are passed to typeset; whether we are OK with the implications of the foregoing when the -x option is also present. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-28 0:24 ` Bart Schaefer @ 2020-11-28 7:32 ` Bart Schaefer 2020-11-28 12:05 ` Felipe Contreras 1 sibling, 0 replies; 53+ messages in thread From: Bart Schaefer @ 2020-11-28 7:32 UTC (permalink / raw) To: Zsh hackers list On Fri, Nov 27, 2020 at 4:24 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > To write the proposed new test cases, we need to decide (this list may > not be all-inclusive): More items: what should ${(t)var} do what should the (i) and (I) subscript flags do ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-28 0:24 ` Bart Schaefer 2020-11-28 7:32 ` Bart Schaefer @ 2020-11-28 12:05 ` Felipe Contreras 1 sibling, 0 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-28 12:05 UTC (permalink / raw) To: Bart Schaefer; +Cc: Daniel Shahaf, Zsh hackers list On Fri, Nov 27, 2020 at 6:25 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > On Fri, Nov 27, 2020 at 3:38 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > > > The best way to move forward would be to write a patch against the Test/ > > directory that specifies the proposed behaviour. Use the "f" flag so > > all newly-added tests will run, rather than just the first. > > There are existing tests that specifically check for the current > behavior, so it's not as if this were simply overlooked. > > To write the proposed new test cases, we need to decide (this list may > not be all-inclusive): Yeah, I agree it's not as straightforward as it initially seemed. I can write a test case for what I think should be the desired behavior in the typical case: "typeset var" does *not* set var to an empty string. But that ignores most of the discussion that has already happened here, and it seems in the Austin CSRG. I bet it's possible to write the code that passes the above test-case, but ten years from now--and if not, it will be twenty years from now--somebody will try to add "local" to POSIX again, and zsh will still be an inconsistent state. Personally, I would rather attempt to do it right today, than add a hack that sort of does what I initially wanted. Maybe we are wasting time chasing multiple tails, but maybe we are onto something. Considering that POSIX hasn't managed to crack the problem after essentially half a century, maybe a couple of mails in this mailing list couldn't hurt. When the solution requires creativity, you just can't know where it could come from. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 18:46 ` Felipe Contreras 2020-11-12 19:10 ` Roman Perepelitsa @ 2020-11-12 19:26 ` Bart Schaefer 2020-11-12 21:48 ` Felipe Contreras 1 sibling, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-12 19:26 UTC (permalink / raw) To: Felipe Contreras; +Cc: Roman Perepelitsa, Zsh hackers list On Thu, Nov 12, 2020 at 10:47 AM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > No. Zsh is not consistent. I did not type /typeset var=''/, I typed > /typeset var/. At the global level you cannot write VAR to create a variable named "VAR". VAR= both creates a variable and assigns it empty string. So now we have to decide what to do when with local variables. They can either have a totally new semantic, or we can follow the semantic for globals. Guess which one makes more sense when you are adding local scope to a language which previously had only two possible conceptions of variables (exist and are empty, or do not exist at all). That said ... > Adding a setopt option for the new behavior doesn't break a lot of > existing zsh code. It probably wouldn't break any _scripts_ even to modify the behavior of KSH_TYPESET for this. Whether we can cleanly perform an implicit unset in the C code structure, and (if not) whether cobbling this in is worthwhile, I haven't investigated or formed an opinion. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 19:26 ` Bart Schaefer @ 2020-11-12 21:48 ` Felipe Contreras 2020-11-13 22:17 ` Bart Schaefer 0 siblings, 1 reply; 53+ messages in thread From: Felipe Contreras @ 2020-11-12 21:48 UTC (permalink / raw) To: Bart Schaefer; +Cc: Roman Perepelitsa, Zsh hackers list On Thu, Nov 12, 2020 at 1:26 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > > On Thu, Nov 12, 2020 at 10:47 AM Felipe Contreras > <felipe.contreras@gmail.com> wrote: > > > > No. Zsh is not consistent. I did not type /typeset var=''/, I typed > > /typeset var/. > So now we have to decide what to do when with local variables. Which is probably the main purpose of typeset (i.e. local). > They > can either have a totally new semantic, or we can follow the semantic > for globals. Syntax is not semantics. var= typeset var= These two have a very similar syntax, so it makes sense that the semantics are the same. But there's no previous equivalent of "typeset var". > Guess which one makes more sense when you are adding > local scope to a language which previously had only two possible > conceptions of variables (exist and are empty, or do not exist at > all). There's a third conception; a non-empty value. var= typeset var= var="foo" typeset var="foo" These are obvious. The only thing that is left is deciding what "typeset var" does. These are the options: 1. Errors 2. Nothing 3. Changes the scope 4. Changes the scope and sets an empty value 5. Changes the scope and sets an arbitrary value Obviously 1 and 2 are not useful options. 5 doesn't really make sense, and 4 is a subset of 5. More importantly; there's already ways to do 4 and 5. So why not do a) something useful, b) something that isn't arbitrary, and c) something that can't be done in other ways? > That said ... > > > Adding a setopt option for the new behavior doesn't break a lot of > > existing zsh code. > > It probably wouldn't break any _scripts_ even to modify the behavior > of KSH_TYPESET for this. Whether we can cleanly perform an implicit > unset in the C code structure, and (if not) whether cobbling this in > is worthwhile, I haven't investigated or formed an opinion. I have already started some experiments. At first glance there doesn't seem to be any straight-forward way of doing this, but I'm not familiar with the code either, so it would take a while for me to reach any conclusion. Either way it seems clear to me reorganizing the code to make it at least possible will remove many of the weird checks and corner cases scattered all over, or at least make them more understandable. We'll have to see. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-12 21:48 ` Felipe Contreras @ 2020-11-13 22:17 ` Bart Schaefer 2020-11-14 0:58 ` Felipe Contreras 0 siblings, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-13 22:17 UTC (permalink / raw) To: Felipe Contreras; +Cc: Roman Perepelitsa, Zsh hackers list On Thu, Nov 12, 2020 at 1:48 PM Felipe Contreras <felipe.contreras@gmail.com> wrote: > > Syntax is not semantics. Um, yes? That was sort of my point. > ... there's no previous equivalent of "typeset var". Also my point. > There's a third conception; a non-empty value. Except that "unset" is not the same as having a non-empty value (I would actually call this simply a "non-value", "empty" has nothing to do with it), from the standpoint of internal representation. I don't happen to agree that they're equatable in the semantics of the language, either, but that opinion is not relevant. Consider this from an evolutionary standpoint. To represent a non-value requires a data structure that knows the name of the object but contains metadata to the effect that the implementation must not reveal to the interpreted program any value corresponding to that name. To represent an unset object merely requires that no data structure exists, period; unset removes the name itself. Given the latter implementation of "unset", we're now asked to declare local scopes. The most straightforward step without an architectural change, is to cause the data structure to come into existence, so that we know its name, and add metadata about its scope; but the existence of the name implies that SOME value becomes visible to the program. The historical precedent for the default behavior is established. The only reason we can even have this discussion now is because in the intervening years those architectural changes have been made and there exists an internal representation for the properties of an invisible "unset" name. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-13 22:17 ` Bart Schaefer @ 2020-11-14 0:58 ` Felipe Contreras 0 siblings, 0 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-14 0:58 UTC (permalink / raw) To: Bart Schaefer; +Cc: Roman Perepelitsa, Zsh hackers list On Fri, Nov 13, 2020 at 4:17 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > Given the latter implementation of "unset", we're now asked to declare > local scopes. The most straightforward step without an architectural > change, is to cause the data structure to come into existence, so that > we know its name, and add metadata about its scope; but the existence > of the name implies that SOME value becomes visible to the program. > The historical precedent for the default behavior is established. The most straightforward way is not necessarily the best way. Very often the best way takes effort. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 18:03 ` Felipe Contreras 2020-11-11 18:16 ` Roman Perepelitsa @ 2020-11-11 18:36 ` Bart Schaefer 2020-11-11 21:08 ` Felipe Contreras 1 sibling, 1 reply; 53+ messages in thread From: Bart Schaefer @ 2020-11-11 18:36 UTC (permalink / raw) To: Felipe Contreras; +Cc: Roman Perepelitsa, Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 1649 bytes --] On Wed, Nov 11, 2020 at 10:04 AM Felipe Contreras < felipe.contreras@gmail.com> wrote: > > And what is the reason why this is not the default? > Remember that doc Daniel quoted? 30 years-ish ago, when implementing zsh as a new shell from scratch, that documentation was used to decide the behavior. At that point the other shells that supported "typeset" were not freeware -- they required expensive licenses or were bundled with commercial operating systems. So the implementation followed the doc (sometimes, it followed a misunderstanding of the doc, which is why for example zsh syntax to specify integer bases differs from ksh) without examples to which to compare. Zsh development has always followed a principle of NOT arbitrarily breaking past usage without an extremely good reason (something I wish other APIs would have taken to heart over the years ... IMO there would be much less abandonware sitting in metaphorical dustbins ... but I digress). So by the time anyone noticed, the behavior you see now was standard practice for zsh in its default modes. Your original example can use ${var:-other} if empty string has no explicit meaning in context. Either way, if "emulate ksh" is supposed to emulate ksh, then it's not > working properly in this instance. > Despite the name, "emulate ksh" is not supposed to perfectly emulate ksh. All it does is change the values of "setopt" to match ksh as closely as possible. A more complete emulation is achieved by actually starting zsh from a symlink named "ksh" (or one of a few equivalent ways). Same goes for "sh" and "bash" (although there is little difference for those two). [-- Attachment #2: Type: text/html, Size: 2303 bytes --] ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 18:36 ` Bart Schaefer @ 2020-11-11 21:08 ` Felipe Contreras 0 siblings, 0 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-11 21:08 UTC (permalink / raw) To: Bart Schaefer; +Cc: Roman Perepelitsa, Zsh hackers list On Wed, Nov 11, 2020 at 12:36 PM Bart Schaefer <schaefer@brasslantern.com> wrote: > On Wed, Nov 11, 2020 at 10:04 AM Felipe Contreras <felipe.contreras@gmail.com> wrote: >> And what is the reason why this is not the default? > > Remember that doc Daniel quoted? > > 30 years-ish ago, when implementing zsh as a new shell from scratch, that documentation was used to decide the behavior. At that point the other shells that supported "typeset" were not freeware -- they required expensive licenses or were bundled with commercial operating systems. So the implementation followed the doc (sometimes, it followed a misunderstanding of the doc, which is why for example zsh syntax to specify integer bases differs from ksh) without examples to which to compare. > > Zsh development has always followed a principle of NOT arbitrarily breaking past usage without an extremely good reason (something I wish other APIs would have taken to heart over the years ... IMO there would be much less abandonware sitting in metaphorical dustbins ... but I digress). So by the time anyone noticed, the behavior you see now was standard practice for zsh in its default modes. This is *in general* a good principle to follow, and it does indeed salvage plenty of projects from the dustbin, but that doesn't mean the rule must be necessarily unquestionably followed. I argue there almost always is a sweet spot. While almost always it's bad to break APIs, not changing them ever also sends projects to the dustbin. The biggest mistake projects make isn't breaking API, but *how* they do it. There are few disadvantages of setting a flag to turn on the new behavior so that people can try it, then enabling the flag by default, while always leaving the possibility to turn the flag off for the people that prefer the old behavior. Doing this once say every 10 years seems like a sensible thing to do. Just have a list of all these proposed changes so they don't get lost. That's what major versions are for. > Your original example can use ${var:-other} if empty string has no explicit meaning in context. I know, but it does have meaning. It is a suffix, so I want to use a space by default "${sfx- }", but only $sfx is unset, it can be set with an empty value, in which case I don't want any suffix. And it's not even my code, it's bash code I'm trying to emulate and leverage from zsh. >> Either way, if "emulate ksh" is supposed to emulate ksh, then it's not >> working properly in this instance. > > Despite the name, "emulate ksh" is not supposed to perfectly emulate ksh. All it does is change the values of "setopt" to match ksh as closely as possible. A more complete emulation is achieved by actually starting zsh from a symlink named "ksh" (or one of a few equivalent ways). Same goes for "sh" and "bash" (although there is little difference for those two). Right, but if virtually all shells do this, and it is a known discrepancy, and I'd argue it's the behavior that makes the most sense, I think it makes sense to have a flag for it. Cheers. -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 16:56 ` Felipe Contreras 2020-11-11 17:02 ` Roman Perepelitsa @ 2020-11-11 17:02 ` Peter Stephenson 2020-11-11 18:05 ` Felipe Contreras 1 sibling, 1 reply; 53+ messages in thread From: Peter Stephenson @ 2020-11-11 17:02 UTC (permalink / raw) To: Zsh hackers list > On 11 November 2020 at 16:56 Felipe Contreras <felipe.contreras@gmail.com> wrote: > If I actually do something on the foo() function: > > typeset var > [[ -n "$1" ]] && var=$1 > echo "var: '${var-other}'" > > I would expect two things: 1) var is not set when I exit the function, > and 2) var is not set until I specifically set it. If you want the variable to be regarded as both local in scope and unset, you can typeset var unset var and the scope stays local, so this is safe. (I thought we already did something like this in emulation but I may not be remembering correctly.) pws ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: Bug with unset variables 2020-11-11 17:02 ` Peter Stephenson @ 2020-11-11 18:05 ` Felipe Contreras 0 siblings, 0 replies; 53+ messages in thread From: Felipe Contreras @ 2020-11-11 18:05 UTC (permalink / raw) To: Peter Stephenson; +Cc: Zsh hackers list On Wed, Nov 11, 2020 at 11:02 AM Peter Stephenson <p.w.stephenson@ntlworld.com> wrote: > > > > On 11 November 2020 at 16:56 Felipe Contreras <felipe.contreras@gmail.com> wrote: > > If I actually do something on the foo() function: > > > > typeset var > > [[ -n "$1" ]] && var=$1 > > echo "var: '${var-other}'" > > > > I would expect two things: 1) var is not set when I exit the function, > > and 2) var is not set until I specifically set it. > > If you want the variable to be regarded as both local in scope and > unset, you can > > typeset var > unset var > > and the scope stays local, so this is safe. > > (I thought we already did something like this in emulation but I may > not be remembering correctly.) OK. But why isn't zsh doing this by default? -- Felipe Contreras ^ permalink raw reply [flat|nested] 53+ messages in thread
end of thread, other threads:[~2020-11-28 12:05 UTC | newest] Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-11-11 15:57 Bug with unset variables Felipe Contreras 2020-11-11 16:13 ` Roman Perepelitsa 2020-11-11 16:56 ` Felipe Contreras 2020-11-11 17:02 ` Roman Perepelitsa 2020-11-11 18:03 ` Felipe Contreras 2020-11-11 18:16 ` Roman Perepelitsa 2020-11-11 20:42 ` Felipe Contreras 2020-11-12 0:20 ` Mikael Magnusson 2020-11-12 1:10 ` Felipe Contreras 2020-11-12 8:45 ` Roman Perepelitsa 2020-11-12 10:47 ` Peter Stephenson 2020-11-12 18:48 ` Bart Schaefer 2020-11-12 19:49 ` Felipe Contreras 2020-11-12 18:46 ` Felipe Contreras 2020-11-12 19:10 ` Roman Perepelitsa 2020-11-12 21:08 ` Felipe Contreras 2020-11-13 8:51 ` Roman Perepelitsa 2020-11-14 0:52 ` Felipe Contreras 2020-11-14 5:41 ` Roman Perepelitsa 2020-11-16 19:41 ` Felipe Contreras 2020-11-16 20:22 ` Roman Perepelitsa 2020-11-17 20:28 ` Felipe Contreras 2020-11-18 22:45 ` Daniel Shahaf 2020-11-22 1:20 ` Felipe Contreras 2020-11-23 4:00 ` Daniel Shahaf 2020-11-23 6:18 ` Felipe Contreras 2020-11-19 2:59 ` Bart Schaefer 2020-11-22 1:50 ` Felipe Contreras 2020-11-17 20:54 ` Bart Schaefer 2020-11-22 1:49 ` Felipe Contreras 2020-11-23 6:48 ` Bart Schaefer 2020-11-23 7:26 ` Felipe Contreras 2020-11-23 20:26 ` Bart Schaefer 2020-11-23 23:39 ` Felipe Contreras 2020-11-24 0:52 ` Bart Schaefer 2020-11-25 8:46 ` Felipe Contreras 2020-11-27 15:44 ` Daniel Shahaf 2020-11-27 20:49 ` Felipe Contreras 2020-11-27 20:59 ` Daniel Shahaf 2020-11-27 21:33 ` Bart Schaefer 2020-11-27 23:37 ` Daniel Shahaf 2020-11-27 23:45 ` Bart Schaefer 2020-11-28 0:24 ` Bart Schaefer 2020-11-28 7:32 ` Bart Schaefer 2020-11-28 12:05 ` Felipe Contreras 2020-11-12 19:26 ` Bart Schaefer 2020-11-12 21:48 ` Felipe Contreras 2020-11-13 22:17 ` Bart Schaefer 2020-11-14 0:58 ` Felipe Contreras 2020-11-11 18:36 ` Bart Schaefer 2020-11-11 21:08 ` Felipe Contreras 2020-11-11 17:02 ` Peter Stephenson 2020-11-11 18:05 ` Felipe Contreras
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).