My variable's value is 0, but I didn't set it to 0

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
7
down vote

favorite












Today I noticed one of my zsh functions is not functioning; I investigated the issue, and the culprit was this:



for i in a b
do
echo "$i"
done
0
0


Then I opened a new zsh, and in that, things were working normally:



for i in a b
do
echo "$i"
done
a
b


Can anyone explain the reason behind the first one acting weird to me?







share|improve this question


















  • 3




    Was variable i previously typeset (or declared) as an integer in the first case?
    – steeldriver
    Aug 18 at 18:48










  • @steeldriver I changed i to weirdName13 and it indeed fixed the issue. But I hadn't done anything with i. How can one undo this typeset? And how can I protect my scripts when i is typeset as an integer?
    – HappyFace
    Aug 18 at 19:27






  • 1




    @HappyFace if you haven't declared your function's local variables as local, expect them to be stomped by random things.
    – muru
    Aug 19 at 1:21














up vote
7
down vote

favorite












Today I noticed one of my zsh functions is not functioning; I investigated the issue, and the culprit was this:



for i in a b
do
echo "$i"
done
0
0


Then I opened a new zsh, and in that, things were working normally:



for i in a b
do
echo "$i"
done
a
b


Can anyone explain the reason behind the first one acting weird to me?







share|improve this question


















  • 3




    Was variable i previously typeset (or declared) as an integer in the first case?
    – steeldriver
    Aug 18 at 18:48










  • @steeldriver I changed i to weirdName13 and it indeed fixed the issue. But I hadn't done anything with i. How can one undo this typeset? And how can I protect my scripts when i is typeset as an integer?
    – HappyFace
    Aug 18 at 19:27






  • 1




    @HappyFace if you haven't declared your function's local variables as local, expect them to be stomped by random things.
    – muru
    Aug 19 at 1:21












up vote
7
down vote

favorite









up vote
7
down vote

favorite











Today I noticed one of my zsh functions is not functioning; I investigated the issue, and the culprit was this:



for i in a b
do
echo "$i"
done
0
0


Then I opened a new zsh, and in that, things were working normally:



for i in a b
do
echo "$i"
done
a
b


Can anyone explain the reason behind the first one acting weird to me?







share|improve this question














Today I noticed one of my zsh functions is not functioning; I investigated the issue, and the culprit was this:



for i in a b
do
echo "$i"
done
0
0


Then I opened a new zsh, and in that, things were working normally:



for i in a b
do
echo "$i"
done
a
b


Can anyone explain the reason behind the first one acting weird to me?









share|improve this question













share|improve this question




share|improve this question








edited Aug 18 at 21:27









Gilles

507k12010031531




507k12010031531










asked Aug 18 at 18:37









HappyFace

1018




1018







  • 3




    Was variable i previously typeset (or declared) as an integer in the first case?
    – steeldriver
    Aug 18 at 18:48










  • @steeldriver I changed i to weirdName13 and it indeed fixed the issue. But I hadn't done anything with i. How can one undo this typeset? And how can I protect my scripts when i is typeset as an integer?
    – HappyFace
    Aug 18 at 19:27






  • 1




    @HappyFace if you haven't declared your function's local variables as local, expect them to be stomped by random things.
    – muru
    Aug 19 at 1:21












  • 3




    Was variable i previously typeset (or declared) as an integer in the first case?
    – steeldriver
    Aug 18 at 18:48










  • @steeldriver I changed i to weirdName13 and it indeed fixed the issue. But I hadn't done anything with i. How can one undo this typeset? And how can I protect my scripts when i is typeset as an integer?
    – HappyFace
    Aug 18 at 19:27






  • 1




    @HappyFace if you haven't declared your function's local variables as local, expect them to be stomped by random things.
    – muru
    Aug 19 at 1:21







3




3




Was variable i previously typeset (or declared) as an integer in the first case?
– steeldriver
Aug 18 at 18:48




Was variable i previously typeset (or declared) as an integer in the first case?
– steeldriver
Aug 18 at 18:48












@steeldriver I changed i to weirdName13 and it indeed fixed the issue. But I hadn't done anything with i. How can one undo this typeset? And how can I protect my scripts when i is typeset as an integer?
– HappyFace
Aug 18 at 19:27




@steeldriver I changed i to weirdName13 and it indeed fixed the issue. But I hadn't done anything with i. How can one undo this typeset? And how can I protect my scripts when i is typeset as an integer?
– HappyFace
Aug 18 at 19:27




1




1




@HappyFace if you haven't declared your function's local variables as local, expect them to be stomped by random things.
– muru
Aug 19 at 1:21




@HappyFace if you haven't declared your function's local variables as local, expect them to be stomped by random things.
– muru
Aug 19 at 1:21










1 Answer
1






active

oldest

votes

















up vote
10
down vote



accepted










% typeset -i i
% for i in a b; print $i
0
0


Variables in zsh can be assigned various types, above -i for "represent internally as an integer", which will cause the variable to be represented as that. This can also be done via integer i. There are various ways to inspect what a variable is:



% print $(t)i
integer
% typeset -p i
typeset -i i=0


And the usual shell + to disable (see also set -x, set +x) it:



% typeset +i i
% for i in a b; print $i
a
b


It may be beneficial to hunt down what changed the type of that variable and restrict that change to a local scope (within a function) so that the global namespace is not polluted with random types, especially on oft used throwaway variable names such as i. It is rather easy to pollute the global namespace, as all that requires is assignment to an undeclared variable:



% () local l=42; g=43 
% print $l

% print $g
43


Or someone could needlessly add the -g flag to a typeset which makes the variable global:



% () typeset -g -i h=42 
% for h in a b; print $h
0
0


Exported variables may persist into new processes (a non-subshell child via fork, or a replacement via exec), but not the type:



% export -i h=42
% print $h $(t)h
42 integer-export

% ( print $(t)h )
integer-export

% exec zsh -l
% print $h $(t)h
42 scalar-export





share|improve this answer






















  • Is it possible to protect a script against this pollution?
    – HappyFace
    Aug 18 at 19:30






  • 2




    "a script" runs as a different process, as I understand it, so should not be affected. if you are sourcing random code (., source, eval) into an existing process then bad code could easily pollute the environment, in which case you'll either need to not do that, or audit every line of the random code to see what it does
    – thrig
    Aug 18 at 19:55






  • 2




    I think you could also unset var to make it lose any special properties it may have. Well, unless it's also readonly, in which case you'd need to typeset +r var first. Bash and ksh could have the same issue with variables set as integers, with the same solution. Except that you can't unset readonly variables in them.
    – ilkkachu
    Aug 18 at 20:38






  • 1




    @ilkkachu, also, in bash or mksh, you may need to call unset several times in case it has been declared local in several ancestor contexts (in those (and yash, unset doesn't unset, it peels off one layer of local (except in bash when the variable has been declared in the current context)).
    – Stéphane Chazelas
    Aug 19 at 8:30










  • What's a non-subshell child via fork? export is for scalar variables to be transmitted across execs, that's independent of processes.
    – Stéphane Chazelas
    Aug 19 at 13:56










Your Answer







StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f463392%2fmy-variables-value-is-0-but-i-didnt-set-it-to-0%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
10
down vote



accepted










% typeset -i i
% for i in a b; print $i
0
0


Variables in zsh can be assigned various types, above -i for "represent internally as an integer", which will cause the variable to be represented as that. This can also be done via integer i. There are various ways to inspect what a variable is:



% print $(t)i
integer
% typeset -p i
typeset -i i=0


And the usual shell + to disable (see also set -x, set +x) it:



% typeset +i i
% for i in a b; print $i
a
b


It may be beneficial to hunt down what changed the type of that variable and restrict that change to a local scope (within a function) so that the global namespace is not polluted with random types, especially on oft used throwaway variable names such as i. It is rather easy to pollute the global namespace, as all that requires is assignment to an undeclared variable:



% () local l=42; g=43 
% print $l

% print $g
43


Or someone could needlessly add the -g flag to a typeset which makes the variable global:



% () typeset -g -i h=42 
% for h in a b; print $h
0
0


Exported variables may persist into new processes (a non-subshell child via fork, or a replacement via exec), but not the type:



% export -i h=42
% print $h $(t)h
42 integer-export

% ( print $(t)h )
integer-export

% exec zsh -l
% print $h $(t)h
42 scalar-export





share|improve this answer






















  • Is it possible to protect a script against this pollution?
    – HappyFace
    Aug 18 at 19:30






  • 2




    "a script" runs as a different process, as I understand it, so should not be affected. if you are sourcing random code (., source, eval) into an existing process then bad code could easily pollute the environment, in which case you'll either need to not do that, or audit every line of the random code to see what it does
    – thrig
    Aug 18 at 19:55






  • 2




    I think you could also unset var to make it lose any special properties it may have. Well, unless it's also readonly, in which case you'd need to typeset +r var first. Bash and ksh could have the same issue with variables set as integers, with the same solution. Except that you can't unset readonly variables in them.
    – ilkkachu
    Aug 18 at 20:38






  • 1




    @ilkkachu, also, in bash or mksh, you may need to call unset several times in case it has been declared local in several ancestor contexts (in those (and yash, unset doesn't unset, it peels off one layer of local (except in bash when the variable has been declared in the current context)).
    – Stéphane Chazelas
    Aug 19 at 8:30










  • What's a non-subshell child via fork? export is for scalar variables to be transmitted across execs, that's independent of processes.
    – Stéphane Chazelas
    Aug 19 at 13:56














up vote
10
down vote



accepted










% typeset -i i
% for i in a b; print $i
0
0


Variables in zsh can be assigned various types, above -i for "represent internally as an integer", which will cause the variable to be represented as that. This can also be done via integer i. There are various ways to inspect what a variable is:



% print $(t)i
integer
% typeset -p i
typeset -i i=0


And the usual shell + to disable (see also set -x, set +x) it:



% typeset +i i
% for i in a b; print $i
a
b


It may be beneficial to hunt down what changed the type of that variable and restrict that change to a local scope (within a function) so that the global namespace is not polluted with random types, especially on oft used throwaway variable names such as i. It is rather easy to pollute the global namespace, as all that requires is assignment to an undeclared variable:



% () local l=42; g=43 
% print $l

% print $g
43


Or someone could needlessly add the -g flag to a typeset which makes the variable global:



% () typeset -g -i h=42 
% for h in a b; print $h
0
0


Exported variables may persist into new processes (a non-subshell child via fork, or a replacement via exec), but not the type:



% export -i h=42
% print $h $(t)h
42 integer-export

% ( print $(t)h )
integer-export

% exec zsh -l
% print $h $(t)h
42 scalar-export





share|improve this answer






















  • Is it possible to protect a script against this pollution?
    – HappyFace
    Aug 18 at 19:30






  • 2




    "a script" runs as a different process, as I understand it, so should not be affected. if you are sourcing random code (., source, eval) into an existing process then bad code could easily pollute the environment, in which case you'll either need to not do that, or audit every line of the random code to see what it does
    – thrig
    Aug 18 at 19:55






  • 2




    I think you could also unset var to make it lose any special properties it may have. Well, unless it's also readonly, in which case you'd need to typeset +r var first. Bash and ksh could have the same issue with variables set as integers, with the same solution. Except that you can't unset readonly variables in them.
    – ilkkachu
    Aug 18 at 20:38






  • 1




    @ilkkachu, also, in bash or mksh, you may need to call unset several times in case it has been declared local in several ancestor contexts (in those (and yash, unset doesn't unset, it peels off one layer of local (except in bash when the variable has been declared in the current context)).
    – Stéphane Chazelas
    Aug 19 at 8:30










  • What's a non-subshell child via fork? export is for scalar variables to be transmitted across execs, that's independent of processes.
    – Stéphane Chazelas
    Aug 19 at 13:56












up vote
10
down vote



accepted







up vote
10
down vote



accepted






% typeset -i i
% for i in a b; print $i
0
0


Variables in zsh can be assigned various types, above -i for "represent internally as an integer", which will cause the variable to be represented as that. This can also be done via integer i. There are various ways to inspect what a variable is:



% print $(t)i
integer
% typeset -p i
typeset -i i=0


And the usual shell + to disable (see also set -x, set +x) it:



% typeset +i i
% for i in a b; print $i
a
b


It may be beneficial to hunt down what changed the type of that variable and restrict that change to a local scope (within a function) so that the global namespace is not polluted with random types, especially on oft used throwaway variable names such as i. It is rather easy to pollute the global namespace, as all that requires is assignment to an undeclared variable:



% () local l=42; g=43 
% print $l

% print $g
43


Or someone could needlessly add the -g flag to a typeset which makes the variable global:



% () typeset -g -i h=42 
% for h in a b; print $h
0
0


Exported variables may persist into new processes (a non-subshell child via fork, or a replacement via exec), but not the type:



% export -i h=42
% print $h $(t)h
42 integer-export

% ( print $(t)h )
integer-export

% exec zsh -l
% print $h $(t)h
42 scalar-export





share|improve this answer














% typeset -i i
% for i in a b; print $i
0
0


Variables in zsh can be assigned various types, above -i for "represent internally as an integer", which will cause the variable to be represented as that. This can also be done via integer i. There are various ways to inspect what a variable is:



% print $(t)i
integer
% typeset -p i
typeset -i i=0


And the usual shell + to disable (see also set -x, set +x) it:



% typeset +i i
% for i in a b; print $i
a
b


It may be beneficial to hunt down what changed the type of that variable and restrict that change to a local scope (within a function) so that the global namespace is not polluted with random types, especially on oft used throwaway variable names such as i. It is rather easy to pollute the global namespace, as all that requires is assignment to an undeclared variable:



% () local l=42; g=43 
% print $l

% print $g
43


Or someone could needlessly add the -g flag to a typeset which makes the variable global:



% () typeset -g -i h=42 
% for h in a b; print $h
0
0


Exported variables may persist into new processes (a non-subshell child via fork, or a replacement via exec), but not the type:



% export -i h=42
% print $h $(t)h
42 integer-export

% ( print $(t)h )
integer-export

% exec zsh -l
% print $h $(t)h
42 scalar-export






share|improve this answer














share|improve this answer



share|improve this answer








edited Aug 19 at 13:44

























answered Aug 18 at 19:26









thrig

22.6k12853




22.6k12853











  • Is it possible to protect a script against this pollution?
    – HappyFace
    Aug 18 at 19:30






  • 2




    "a script" runs as a different process, as I understand it, so should not be affected. if you are sourcing random code (., source, eval) into an existing process then bad code could easily pollute the environment, in which case you'll either need to not do that, or audit every line of the random code to see what it does
    – thrig
    Aug 18 at 19:55






  • 2




    I think you could also unset var to make it lose any special properties it may have. Well, unless it's also readonly, in which case you'd need to typeset +r var first. Bash and ksh could have the same issue with variables set as integers, with the same solution. Except that you can't unset readonly variables in them.
    – ilkkachu
    Aug 18 at 20:38






  • 1




    @ilkkachu, also, in bash or mksh, you may need to call unset several times in case it has been declared local in several ancestor contexts (in those (and yash, unset doesn't unset, it peels off one layer of local (except in bash when the variable has been declared in the current context)).
    – Stéphane Chazelas
    Aug 19 at 8:30










  • What's a non-subshell child via fork? export is for scalar variables to be transmitted across execs, that's independent of processes.
    – Stéphane Chazelas
    Aug 19 at 13:56
















  • Is it possible to protect a script against this pollution?
    – HappyFace
    Aug 18 at 19:30






  • 2




    "a script" runs as a different process, as I understand it, so should not be affected. if you are sourcing random code (., source, eval) into an existing process then bad code could easily pollute the environment, in which case you'll either need to not do that, or audit every line of the random code to see what it does
    – thrig
    Aug 18 at 19:55






  • 2




    I think you could also unset var to make it lose any special properties it may have. Well, unless it's also readonly, in which case you'd need to typeset +r var first. Bash and ksh could have the same issue with variables set as integers, with the same solution. Except that you can't unset readonly variables in them.
    – ilkkachu
    Aug 18 at 20:38






  • 1




    @ilkkachu, also, in bash or mksh, you may need to call unset several times in case it has been declared local in several ancestor contexts (in those (and yash, unset doesn't unset, it peels off one layer of local (except in bash when the variable has been declared in the current context)).
    – Stéphane Chazelas
    Aug 19 at 8:30










  • What's a non-subshell child via fork? export is for scalar variables to be transmitted across execs, that's independent of processes.
    – Stéphane Chazelas
    Aug 19 at 13:56















Is it possible to protect a script against this pollution?
– HappyFace
Aug 18 at 19:30




Is it possible to protect a script against this pollution?
– HappyFace
Aug 18 at 19:30




2




2




"a script" runs as a different process, as I understand it, so should not be affected. if you are sourcing random code (., source, eval) into an existing process then bad code could easily pollute the environment, in which case you'll either need to not do that, or audit every line of the random code to see what it does
– thrig
Aug 18 at 19:55




"a script" runs as a different process, as I understand it, so should not be affected. if you are sourcing random code (., source, eval) into an existing process then bad code could easily pollute the environment, in which case you'll either need to not do that, or audit every line of the random code to see what it does
– thrig
Aug 18 at 19:55




2




2




I think you could also unset var to make it lose any special properties it may have. Well, unless it's also readonly, in which case you'd need to typeset +r var first. Bash and ksh could have the same issue with variables set as integers, with the same solution. Except that you can't unset readonly variables in them.
– ilkkachu
Aug 18 at 20:38




I think you could also unset var to make it lose any special properties it may have. Well, unless it's also readonly, in which case you'd need to typeset +r var first. Bash and ksh could have the same issue with variables set as integers, with the same solution. Except that you can't unset readonly variables in them.
– ilkkachu
Aug 18 at 20:38




1




1




@ilkkachu, also, in bash or mksh, you may need to call unset several times in case it has been declared local in several ancestor contexts (in those (and yash, unset doesn't unset, it peels off one layer of local (except in bash when the variable has been declared in the current context)).
– Stéphane Chazelas
Aug 19 at 8:30




@ilkkachu, also, in bash or mksh, you may need to call unset several times in case it has been declared local in several ancestor contexts (in those (and yash, unset doesn't unset, it peels off one layer of local (except in bash when the variable has been declared in the current context)).
– Stéphane Chazelas
Aug 19 at 8:30












What's a non-subshell child via fork? export is for scalar variables to be transmitted across execs, that's independent of processes.
– Stéphane Chazelas
Aug 19 at 13:56




What's a non-subshell child via fork? export is for scalar variables to be transmitted across execs, that's independent of processes.
– Stéphane Chazelas
Aug 19 at 13:56

















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f463392%2fmy-variables-value-is-0-but-i-didnt-set-it-to-0%23new-answer', 'question_page');

);

Post as a guest













































































Comments

Popular posts from this blog

What does second last employer means? [closed]

Installing NextGIS Connect into QGIS 3?

One-line joke