What is lexical scope?

2018-12-31 04:21发布

Could someone please give me a brief introduction to lexical scoping?

13条回答
看风景的人
2楼-- · 2018-12-31 04:31

I understand them through examples. :)

First, Lexical Scope (also called Static Scope), in C-like syntax:

void fun()
{
    int x = 5;

    void fun2()
    {
        printf("%d", x);
    }
}

Every inner level can access its outer levels.

There is another way, called Dynamic Scope used by first implementation of Lisp, again in C-like Syntax:

void fun()
{
    printf("%d", x);
}

void dummy1()
{
    int x = 5;

    fun();
}

void dummy2()
{
    int x = 10;

    fun();
}

Here fun can either access x in dummy1 or dummy2, or any x in any function that call fun with x declared in it.

dummy1();

will print 5,

dummy2();

will print 10.

The first one is called static because it can be deduced at compile-time, the second is called dynamic because the outer scope is dynamic and depends on the chain call of the functions.

I find static scoping easier for the eye. Most languages went this way eventually even Lisp(can do both, right?). Dynamic scoping is like passing references of all variables to the called function.

An example of why the compiler can not deduce the outer dynamic scope of a function, consider our last example, if we write something like this:

if(/* some condition */)
    dummy1();
else
    dummy2();

The call chain depends on a run time condition. If it is true, then the call chain looks like:

dummy1 --> fun()

If the condition is false:

dummy2 --> fun()

The outer scope of fun in both cases is the caller plus the caller of the caller and so on.

Just to mention that C language does not allow nested functions nor dynamic scoping.

查看更多
回忆,回不去的记忆
3楼-- · 2018-12-31 04:33

Lexical Scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope. This means that the child functions are lexically bound to the execution context of their parents. Lexical scope is sometimes also referred to as Static Scope.

function grandfather() {
    var name = 'Hammad';
    // likes is not accessible here
    function parent() {
        // name is accessible here
        // likes is not accessible here
        function child() {
            // Innermost level of the scope chain
            // name is also accessible here
            var likes = 'Coding';
        }
    }
}

The thing you will notice about lexical scope is that it works forward, meaning name can be accessed by its children's execution contexts. But it doesn't work backward to its parents, meaning that the variable likes cannot be accessed by its parents. This also tells us that variables having the same name in different execution contexts gain precedence from top to bottom of the execution stack. A variable, having a name similar to another variable, in the innermost function (topmost context of the execution stack) will have higher precedence.

Note this is taken from here

查看更多
不再属于我。
4楼-- · 2018-12-31 04:39

A lexical scope in Javascript means that a variable defined outside a function can be accessible inside another function defined after the variable declaration. But the opposite is not true, the variables defined inside a function will not be accessible outside that function.

This concept is heavily used in closures in Javascript.

Let say we have the below code.

var x = 2;
var add = function() {
var y = 1;
return x + y;
};

Now, when you call add() --> this will print 3.

So, add() function is accessing the global variable x which is defined before method function add. This is called due to lexical scoping in javascript.

查看更多
弹指情弦暗扣
5楼-- · 2018-12-31 04:42

Here's a different angle on this question that we can get by taking a step back and looking at the role of scoping in the larger framework of interpretation (running a program). In other words, imagine that you were building an interpreter (or compiler) for a language and were responsible for computing the output, given a program and some input to it.

Interpretation involves keeping track of three things:

1) State - namely, variables and referenced memory locations on the heap and stack.

2) Operations on that state - namely, every line of code in your program

3) The Environment in which a given Operation runs - namely, the projection of State on an Operation.

An interpreter starts at the first line of code in a program, computes its environment, runs the line in that environment and captures its effect on the program's state. It then follows the program's control flow to execute the next line of code, and repeats the process till the program ends.

The way you compute the environment for any operation is through a formal set of rules defined by the programming language. The term "binding" is frequently used to describe the mapping of the overall state of the program to a value in the environment. Note that by "overall state" we do not mean global state, but rather the sum total of every reachable definition, at any point in the execution)

This is the framework in which the scoping problem is defined. Now to the next part of what our options are.

  • As the implementor of the interpreter, you could simplify your task by making the environment as close as possible to the program's state. Accordingly, the environment of a line of code would simply be defined by environment of the previous line of code with the effects of that operation applied to it, regardless of whether the previous line was an assignment, a function call, return from a function, or a control structure such as a while loop.

This is the gist of dynamic scoping, wherein the environment that any code runs in is bound to the state of the program as defined by its execution context.

  • Or, you could think of a programmer using your language and simplify his or her task of keeping track of the values a variable can take. There are way too many paths and too much complexity involved in reasoning about the outcome the totality of past execution. Lexical Scoping helps do this by restricting the current environment to the portion of state defined in the current block, function or other unit of scope, and its parent (i.e. the block enclosing the current clock, or the function that called the present function).

In other words, with Lexical Scope the environment that any code sees is bound to state associated with a scope defined explicitly in the language, such as a block or a function.

查看更多
不流泪的眼
6楼-- · 2018-12-31 04:44

Lets try the shortest possible definition:

Lexical Scoping defines how variable names are resolved in nested functions: inner functions contain the scope of parent functions even if the parent function has returned.

That is all there is to it!

查看更多
闭嘴吧你
7楼-- · 2018-12-31 04:47

There is an important part of the conversation surrounding Lexical and Dynamic Scoping that is missing: a plain explanation of the lifetime of the scoped variable - or when the variable can be accessed.

Dynamic scoping only very loosely corresponds to "global" scoping in the way that we traditionally think about it (the reason I bring up the comparison between the two is that it has already been mentioned - and I don't particularly like the linked article's explanation); it is probably best we don't make the comparison between global and dynamic - though supposedly, according to the linked article, "...[it] is useful as a substitute for globally scoped variables."

So, in plain English, what's the important distinction between the two scoping mechanisms?

Lexical scoping has been defined very well throughout the answers above: lexically scoped variables are available - or, accessible - at the local level of the function in which it was defined.

However - as it is not the focus of the OP - dynamic scoping has not received a great deal of attention and the attention it has received means it probably needs a bit more (that's not a criticism of other answers, but rather a "oh, that answer made we wish there was a bit more"). So, here's a little bit more:

Dynamic scoping means that a variable is accessible to the larger program during the lifetime of the function call - or, while the function is executing. Really, Wikipedia actually does a nice job with the explanation of the difference between the two. So as not to obfuscate it, here is the text that describes dynamic scoping:

...[I]n dynamic scoping (or dynamic scope), if a variable name's scope is a certain function, then its scope is the time-period during which the function is executing: while the function is running, the variable name exists, and is bound to its variable, but after the function returns, the variable name does not exist.

查看更多
登录 后发表回答