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:local [2012/01/31 14:45]
ormaaj [Description] finish paragraph.
commands:builtin:local [2012/04/23 01:30]
Line 2: Line 2:
 ===== Synopsis ===== ===== Synopsis =====
-===== Description ===== 
-<WRAP center round todo 60%> 
-TODO: Describe Bash scope rules in some detail. Point pages like [[commands:​builtin:​declare]] and those dealing with functions here for more details on locals and dynamic scope. This wiki could use a dedicated article about functions. Not sure how to organize all this information yet. Help if you can. ^_^ 
-The most important thing to know about variable scope in Bash is that the variables visible from within the body of a function are always the same as those which are visible //at the time a function is called//. Two equivalent ways of stating how this works: 
-  * A called function sees a cascading view of all variables out to the first caller which declared a local by a given name. Variable scope works much like subclass polymorphism in this way, or CSS inheritance. 
-Or alternatively:​ 
-  * All descendant callees of a function see locals defined in the scope of the caller until another function defines a local of the same name, whose callees and all further descendents will then see the new variable. 
-This differs from the majority of other languages except those with so-called [[http://​​dynamic-scope|dynamic scope]], though shell functions are so vastly unconventional in other ways that it's difficult to judge whether this behavior is good or bad by contrast to the conventions of other languages. If a function doesn'​t take care to locally define the variables used by commands then the value of any given variable can differ depending on the context from which it is called. Alternatively,​ almost all gotchas regarding use of global variables in most languages also apply at least equally to Bash, if not moreso, as Bash lacks namespaces and a powerful type system. ​ 
-This discussion inevitably brings up questions about closures, first-class-functions,​ higher-order-functions,​ continuations,​ function-objects,​ and the like. The answer is that these concepts are rarely applicable to Bash for the aforementioned reason that "​functions"​ are just distantly reminiscent of what one would typically call a "​conventional"​ function. Function definitions can't be nested [[howto/​collapsing_functions|in the usual sense]], nor can they be passed around to, or returned from functions either as objects or by reference. 
-===== Examples ===== 
-Notice that nesting function definitions doesn'​t impact the results. 
 <​code>​ <​code>​
-$ ( f() { local x=2; g() { echo "​$x";​ }; }; f; g ) +local [option] name[=value] ...
- +
-$ ( f() { local x=2; g() { echo "​$x";​ }; g; }; f ) +
-$ ( g() { echo "​$x";​ }; f() { local x=2; g; }; f ) +
 </​code>​ </​code>​
-"​inheritance-like"​ behavior. Notice "​f"​ doesn'​t care that a global "​x"​ is in the scope of the definition. Only "​call-time"​ matters. +===== Description =====
-<​code>​ +
-f() (( +''​local''​ is identical to [[commands:​builtin:​declare|declare]] in every way, and takes all the same options, with two exceptions: 
-    x++ +  * Usage outside of a function is an error. Both ''​declare''​ and ''​local''​ within a function have the same effect on variable scope, including the -option. 
-)) +  * ''​local''​ with no options ​prints ​variable names and values in the same format as ''​declare''​ with no options, except the variables are filtered to print only locals that were set in the same scope from which ''​local''​ was called. Variables in parent scopes are not printed.
- +
-g() { +
-    local +
-    f +
-    echo "​$x"​ +
- +
-g         # ​prints ​+
-echo "​$x"​ # prints 0 +
 ===== Portability considerations ===== ===== Portability considerations =====
-  * In BashZsh, and Mksh, locals referenced ​as arithmetic variables become local at the start of the [[typeset]] command (and are therefore always zero), while parameter expansions have the value of the next-outermost scopeThe only exception is the original Ksh. +  * ''​local''​ is not specified by POSIX. Most bourne-like shells don't have a builtin called ''​local''​but some such as ''​dash'' ​and the busybox shell do.
- +
-<​code>​ +
-# ksh93 only. Infinite recursion in others. +
-$ f() { typeset -i n=${1:​---n};​ if ((n)); then printf $n; f; fi }; f 5 +
-54321 +
- +
-# Bash et al. +
-$ f() { typeset -i n=${1:​-$n-1};​ if ((n)); then printf -- $n; f; fi }; f 5 +
-54321 +
-  * ''​local'' ​is not specified ​by POSIX. Additionally''​local''​ is Bash-only. It is identical to [[declare]] in every way, and takes all the same options, except that usage outside of a function is an error. Using ''​declare'' ​within a function ​has the same effect as local unless the -g option is given. ''​typeset''​ is technically more portable than both ''​local''​ and ''​declare'',​ but labeled as "​depreciated"​ in the Bash manpage.+  * The behavior of function scope is not defined ​by POSIX, ​however ​local variables are implemented widely by bourne-like shells, and behavior differs substantially. Even the''​dash'' ​shell has local variables.
-  * POSIX does not specify function local variables and their behavior is therefore not formally defined and often largely undocumented. The Korn shell and derivatives including Bash and Zsh thankfully mostly agree on semantics (when using the "POSIX-style" ​function ​definition syntax)and overload the typeset ​builtin (or declare and local) ​to declare ​variables ​as local.+  * In ksh93, ​using POSIX-style function ​definitions''​typeset''​ doesn'​t set ''​local''​ variables, but rather acts upon variables of the next-outermost scope (e.g. setting attributes). Using ''​typeset''​ within functions defined using ksh ''​function name {''​ syntax, ​variables ​follow roughly [[http://​​lexical-scope|lexical-scoping]],​ except that functions themselves don't have scope, just like Bash. This means that even functions defined within a "​function'​s scope" don't have access to non-local variables except through ''​namerefs''​.
 ===== See also ===== ===== See also =====
-  * http://​​scripting/​basics#​variable_scope ​(todo: do something about this)+  * http://​​scripting/​basics#​variable_scope
  • commands/builtin/local.txt
  • Last modified: 2012/04/23 01:30
  • by ormaaj