Differences

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

Link to this comparison view

Both sides previous revision Previous revision
commands:builtin:local [2012/02/01 09:02]
ormaaj Turns out a lot of this is wrong. Sorry. :(
commands:builtin:local [2012/04/23 01:30] (current)
ormaaj
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. ^_^ 
-</​WRAP>​ 
- 
-Warning - mountains of fail below on my part. Even I don't understand this after all. Going back to do more testing. 
-<WRAP hide> 
-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://​community.schemewiki.org/?​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 ) +
-2+
 </​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>​ +
-x=0+
  
-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 -g 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() { +===== Portability considerations =====
-    local x +
-    f +
-    echo "​$x"​ +
-}+
  
-g         # prints 1 +  * ''​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.
-echo "​$x"​ # prints 0 +
-</​code>​+
  
-===== Portability considerations =====+  * 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.
  
-  * ''​local'' ​is not specified by POSIX. Additionally, ​''​local'' ​is Bash-only. It is identical to [[declare]] in every way, and takes all the same optionsexcept 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.+  * In ksh93, using POSIX-style function definitions, ​''​typeset'' ​doesn'​t set ''​local'' ​variablesbut 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://​community.schemewiki.org/?​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''​.
  
-  * 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. 
-</​WRAP>​ 
 ===== See also ===== ===== See also =====
  
   * http://​wiki.bash-hackers.org/​scripting/​basics#​variable_scope   * http://​wiki.bash-hackers.org/​scripting/​basics#​variable_scope