Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using "declare" in Zsh

Tags:

zsh

I am following this thread: https://stackoverflow.com/a/19742842/5057251 for typeset (or declare) in ZSH, not BASH.

#Declare (or typeset) an array of integers
#declare -ai int_array
typeset -ai int_array
int_array=(1 2 3)
echo "${int_array[@]}"

Then

# Attempt to change 1st element to string. (expect to fail)
int_array[1]="Should fail" || echo "error: ${LINENO}"
echo "${int_array[@]}"

Bash finds the error, gracefully reports error and lineno, prints:

1 2 3

But Zsh accepts, prints:

Should fail 2 3

Not sure why different.

like image 312
jim rothstein Avatar asked Oct 28 '25 05:10

jim rothstein


1 Answers

There are two problems here:

  1. In bash, and zsh, assigning a string to an integer variable causes that string to be evaluated as an arithmetic expression. Thus, this is not an error:

    $ typeset -i foo
    $ foo="bar"
    

    If bar was a variable previously set to an arithmetic expression, then bar's expansion would be evaluated as such:

    $ bar=10+2
    $ typeset -i foo
    $ foo="bar"
    $ echo "$foo"
    12
    

    The error in your assignment, of course, is that there's no way to expand Should fail like that. If it were, say, Should - fail (an arithmetic expression subtracting the value of the two variables Should and fail, for example, it would still work:

    $ foo="Should - fail"
    $ echo "$foo"
    0
    
  2. The second problem is that nothing in the zsh docs indicate that -i may be set for an entire array, and so the -a in -ai is ignored:

    bash-5.0$ typeset -ai foo
    bash-5.0$ declare -p foo
    declare -ai foo=([0]="0")  # the previous value was retained in the array
    

    vs zsh:

    % typeset -ai foo
    % foo[1]=10
    % foo[2]=20
    % declare -p foo
    typeset -i foo=20  # treated as a normal variable, not array
    

    What you're seeing is essentially int_array being redeclared as an array (without any qualifiers) when you do int_array=(1 2 3):

    % foo=(1 2 3)
    % declare -p foo
    typeset -a foo=( 1 2 3 )
    
like image 57
muru Avatar answered Oct 30 '25 09:10

muru