title: Get length of an empty or unset array when “nounset” option is in effect
body: <p>Due to the fact that Bash, when running in <code>set -o nounset</code> mode (aka <code>set -u</code>), may consider empty arrays as unset regardless of whether they have actually been assigned an empty value, care must be taken when attempting to expand an array — one of the workarounds is to check whether the array length is zero. Not to mention that getting the number of elements in an array is a common operation by itself.</p>
  
  <p>While developing with Bash 4.2.47(1)-release in openSUSE 42.1, I accustomed to that getting array size with <code>${#ARRAY_NAME[@]}</code> succeeds when array is either empty or unset. However, while checking my script with Bash 4.3.46(1)-release in FreeBSD 10.3, it turned out that this operation may fail with generic “unbound variable” error message. Providing default value for expansion does not seem to work for array length. <strong>Providing alternative command chains seems to work, but not inside a function called through a subshell expansion</strong> — functions just exits after the first failure. What else can be of any help here?</p>
  
  <p>Consider the following example:</p>
  
  <pre><code>function Size ()
  {
      declare VAR="$1"
      declare REF="\${#${VAR}[@]}"
      eval "echo \"${REF}\" || echo 0" 2&gt;/dev/null || echo 0
  }
  
  set -u
  declare -a MYARRAY
  
  echo "size: ${#MYARRAY[@]}"
  echo "size: ${#MYARRAY[@]-0}"
  echo "Size: $(Size 'MYARRAY')"
  echo -n "Size: "; Size 'MYARRAY'
  </code></pre>
  
  <p>In openSUSE environment, all <code>echo</code> lines output <code>0</code>, as expected. In FreeBSD, the same outcome is only possible when the array is explicitly assigned an empty value: <code>MYARRAY=()</code>; otherwise, both inline queries in the first two lines fail, the third line just outputs <code>Size:</code> (meaning that the expansion result is empty), and only the last line succeeds completely thanks to the outer <code>|| echo 0</code> — however passing the result through to the screen is not what is usually intended when trying to obtain array length.</p>
  
  <p>Here is the summary of my observations:</p>
  
  <pre><code>                                    Bash 4.2  Bash 4.3
                                      openSUSE  FreeBSD
  
  counting elements of unset array       OK      FAILED
  counting elements of empty array       OK        OK
  
  content expansion of unset array     FAILED    FAILED
  content expansion of unset array(*)    OK        OK
  content expansion of empty array     FAILED    FAILED
  content expansion of empty array(*)    OK        OK
      (* with fallback value supplied)
  </code></pre>
  
  <p>To me, that looks pretty inconsistent. Is there any real future-proof and cross-platform solution for that?</p>