Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
commands:builtin:declare [2012/08/13 16:36]
ormaaj Undocumented goodies. (-c, -n)
commands:builtin:declare [2013/04/14 20:11] (current)
ormaaj mirabilos' example for eventual portability section
Line 34: Line 34:
 |''​[-+]i'' ​ |make NAMEs have the "​integer"​ attribute ​ | |''​[-+]i'' ​ |make NAMEs have the "​integer"​ attribute ​ |
 |''​[-+]l'' ​ |convert NAMEs to lower case on assignment (makes sure the variable contains only lower case letters) ​ | |''​[-+]l'' ​ |convert NAMEs to lower case on assignment (makes sure the variable contains only lower case letters) ​ |
-|''​[-+]n'' ​ |**Git Only!** ​make NAME a reference to the variable named by its value. ​Equivalent to the ''​nameref''​ builtin. An initial implementation is available for testing ​in the ''​devel''​ branch.  |+|''​[-+]n'' ​ |make NAME a reference to the variable named by its value. ​Introduced ​in Bash 4.3-alpha ​ |
 |''​-p'' ​ |display the attributes and value of each NAME  | |''​-p'' ​ |display the attributes and value of each NAME  |
 |''​[-+]r'' ​ |make NAMEs readonly (removing with ''​+r''​ is valid syntax, but not possible) ​ | |''​[-+]r'' ​ |make NAMEs readonly (removing with ''​+r''​ is valid syntax, but not possible) ​ |
Line 56: Line 56:
 ===== Notes ===== ===== Notes =====
  
-Unix shells offer very few datatypes. POSIX(r) specifies only one, strings. Bash and some other shells extend this in an unusual way by allowing "​attributes" ​which represent datatypes ​to be associated with variable names. ​Bash can effectively set these attributes ​in several ways: ''​declare''​''​local''​; the compound assignment syntax; and the function definition syntax. For instancein that sense one way to think about functions is as string variables with the function attribute ​set, that contain bash code which can only be assigned using a funky syntax and dereferenced in a particular way. You can even export them (though many shells don't automatically inherit functions from the environment like Bash does.Datatypes in bash have a few other interesting ​and unusual ​capabilities such as the ability to modify data on assignment. +Unix shells offer very few datatypes. Bash and some other shells extend this by allowing "​attributes"​ to be set on variable names. ​The only attributes ​specified by POSIX are ''​export'' ​and ''​readonly'', ​which are set by their own dedicated builtins. Datatypes in bash have a few other interesting capabilities such as the ability to modify data on assignment.
- +
-The ksh88 manpage mentions that arithmetic performed on variables explicitly declared with the integer attribute outperforms that of ordinary string variables. I have not tested this or found it mentioned elsewhere, but it's something to keep in mind. Polymorphic datatypes used in dynamic programming languages such as Bash do suffer some additional overhead when type checking must occur, and depending on the way the shell is implemented,​ setting the type on variables that will only ever contain integers can move that check from the time it's used to the time it's assigned, reducing that overhead in some cases. +
- +
-It can also improve code safety to guarantee that certain variables will only contain certain types by treating them as you would in a statically typed language. This is considered good practice in many langauges. A somewhat recent trend is to offer a choice of typing in languages which were previously either strictly static or strictly dynamic. C# is one example. Bash has had this ability for a couple decades. 8-)+
  
 ===== Examples ===== ===== Examples =====
Line 85: Line 81:
 } }
 </​code>​ </​code>​
 +
 +==== Nameref ====
 +
 +Bash 4.3 adds a new way to indirectly reference variables. ''​typeset -n''​ can be used to make a variable indirectly refer to another. In Bash, the lvalue of the assignment given to ''​typeset -n''​ will refer to the variable whose name is expanded on the RHS.
 +
 +<​code>​
 +# Sum a set of arrays and assign the result indirectly, also printing each intermediary result (without portability workarounds)
 +# sum name arrname [ arrname ... ]
 +function sum {
 +    typeset -n _result=$1 _arr
 +    typeset IFS=+
 +    _result=0
 +    for _arr in "​${@:​2}";​ do                        # Demonstrate the special property of "​for"​ on a nameref.
 +        (( _result += ${_arr[*]} ))
 +        printf '%s = %d\n' "​${!_result}"​ "​$_result"​ # Demonstrate the special property of ${!ref} on a nameref.
 +    done
 +}
 +
 +a=(1 2 3) b=(6 5 4) c=(2 4 6)
 +sum total a b c
 +printf 'Final value of "​total"​ is: %d\n' "​$total"​
 +</​code>​
 +<div hide>
 +function sum {
 + typeset -n _result=$1
 + shift
 + typeset IFS=+ _arrx
 + _result=0
 + for _arrx in "​$@";​ do                        # Demonstrate the special property of "​for"​ on a nameref.
 + typeset -n _arr=$_arrx
 + (( _result += ${_arr[*]} ))
 + printf '%s = %d\n' "​${!_result}"​ "​$_result"​ # Demonstrate the special property of ${!ref} on a nameref.
 + done
 +}
 +
 +a=(1 2 3); b=(6 5 4); c=(2 4 6)
 +sum total a b c
 +printf 'Final value of "​total"​ is: %d\n' "​$total"​
 +</​div>​
 +
 +''​typeset -n''​ is currently implemented in ksh93, mksh, and Bash 4.3. Bash and mksh's implementations are quite similar, but much different from ksh93'​s. See [[#​portability_considerations | Portability considerations]] for details. ksh93 namerefs are much more powerful than Bash'​s.
  
 ===== Portability considerations ===== ===== Portability considerations =====
  
   * ''​declare''​ is not specified by POSIX(r)   * ''​declare''​ is not specified by POSIX(r)
-  * ''​declare''​ is unique to Bash and totally non-portable with the possible exception of Zsh in Bash compatibility mode. Bash marks the synonym ''​typeset''​ as obsolete, which in Bash behaves identically to ''​declare''​. All other Korn-like shells use ''​typeset'',​ so it probably isn't going away any time soon. Unfortunately,​ being a non-standard builtin, ''​typeset''​ differs significantly between shells. ksh93 also considers ''​typeset''​ a special builtin, while Bash does not - even in POSIX mode. This fact is irrelevant to almost everyone, just that certain crafty tricks involving the environment of ''​typeset''​ in Bash won't work the same way in ksh.+  * ''​declare''​ is unique to Bash and totally non-portable with the possible exception of Zsh in Bash compatibility mode. Bash marks the synonym ''​typeset''​ as obsolete, which in Bash behaves identically to ''​declare''​. All other Korn-like shells use ''​typeset'',​ so it probably isn't going away any time soon. Unfortunately,​ being a non-standard builtin, ''​typeset''​ differs significantly between shells. ksh93 also considers ''​typeset''​ a special builtin, while Bash does not - even in POSIX mode. If you use ''​typeset''​, you should attempt to only use it in portable ways. 
 +  * **todo** nameref portability...
  
 ===== See also ===== ===== See also =====
Line 95: Line 133:
   * [[commands:​builtin:​readonly]]   * [[commands:​builtin:​readonly]]
   * [[commands:​builtin:​unset]]   * [[commands:​builtin:​unset]]
 +  * [[http://​austingroupbugs.net/​view.php?​id=351 | declaration commands]] will change the behavior of certain builtins such as ''​export''​ in the next version of POSIX.
  • commands/builtin/declare.1344875801.txt
  • Last modified: 2012/08/13 16:36
  • by ormaaj