4

I've noticed that some languages like C, C++, Java, Perl, and .NET Visual Basic have "block" scoping which means that a variable will only be defined within the specific code block it was declared in.

For example (C++):

if (true) {
    int x = 1;
}
std::cout << x << std::endl;

This code will fail to compile since x is only visible within the block scope created by the if statement.

error: 'x' was not declared in this scope


But languages like VBA, Python, and Javascript have "function based" scoping which means that the only time a new scope is created is when a new function is defined.

For example (VBA):

If True Then
    Dim x As Integer
    x = 1
End If
MsgBox(x)

This code runs successfully and the value of x is visible outside of the if statement.

This type of scoping seems rather confusing to me because visually it looks like x should "belong" to the if statement.


So this raises the question: Are there any advantages other than just look and feel... like performance advantages/compile speed advantages/etc... for a language to be "function" scoped rather than "block" scoped?

tjwrona1992
  • 239
  • 2
  • 10
  • [What is the problem with "Pros and Cons"?](http://meta.softwareengineering.stackexchange.com/q/6758/31260) – gnat Feb 09 '17 at 16:15
  • 1
    @gnat I'm not looking for pros and cons. I'm just wondering if there actually are performance differences or if it is just a stylistic preference. – tjwrona1992 Feb 09 '17 at 17:10

1 Answers1

8

In theory, function scope should actually be faster - variables are typically created in a stack frame, and function scope would only create that stack frame once, while block scope would need to repeadedly open up a new stack frame in every block.

In practice, there are several facts that invalidate that initial assumption:

  1. No compiler is forced to create a stack frame for a block only if a specific block is actually reached - And most compilers do exactly that - A stack frame is being created that holds room for the superset of all variables that are part of the function. Languages like C only define compile-time accessibility of a variable. So, the compiler must only make sure that access to a variable that is not currently in scope is forbidden - Not that this variable is not present at all. That is a rule that can be enforced at compile time. Note that good compilers can even re-use space in the stack frame that is used by variables with non-overlapping scope and will sort and consolidate all variables in a stack frame to ensure maximum memory re-use.
  2. Block scope can allow better usage of register variables if the compiler is clever enough and enough registers are available - Because variables in a block only need to have the lifetime of the block, they can be re-used earlier.

So, from a performance viewpoint, I don't actually see advantages for both approaches - As pointed out above, you can technically implement function scope even if the language asks for block scope. That might waste some memory, though.

From a programmer's standpoint, I do see, however, clear advantages for block scope (that might, however, just be because I grew up with languages like C and C++)

tofro
  • 891
  • 6
  • 10
  • 2
    Performance comes into play once you have closures. – CodesInChaos Feb 09 '17 at 17:22
  • Block- or function-scoped in a strict sense doesn't really apply to closures. They're neither, or rather reference-scoped. – tofro Feb 09 '17 at 17:31
  • 2
    To add: a typical optimizing compiler will use variable assignment and usage analysis to find the smallest/shortest lifetime rather than using the declared scope (because the analysis is more accurate and may find a shorter lifetime than the block of scope). What that means for an optimizing compiler, is that it can promote all block scoped variables to function scope, and then use its sophisticated analyses to limit lifetimes and promote register reuse. This means there is effectively no difference between function scope and block scope in terms of performance in optimized code. – Erik Eidt Feb 09 '17 at 17:31
  • 1
    @tofro Scope is just the region of code where you can use the name of the variable. Block scope vs function scope matters a lot for closures, because it determines if a block that's entered multiple times gets a new variable or reused the same variable. – CodesInChaos Feb 09 '17 at 17:35
  • @CodesInChaos I'm not sure you can compare the cases performance-wise if you see it that way - after all, you "get something for your money" and your programs do something different. – tofro Feb 09 '17 at 17:45
  • @CodesInChaos, that is a great point. Still, for comparison, when a new variable is the effect you want in a strictly function scoped language, you have to introduce a new (usually nested) function and then call it, re: [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression), which is to say an entire new function closure might have to be created just to get that effect. – Erik Eidt Feb 09 '17 at 17:48
  • 2
    To me, it just seems like function based scoping reads very poorly... I just didn't understand why anyone would want to implement a language with function based scoping if there were no clear performance advantages! I trip over my own variables all the time whenever I program in VBA because of how it handles scoping... – tjwrona1992 Feb 09 '17 at 19:14
  • I should add that in VBA, unless you specify `Option Explicit`, a procedure-level variable needs not be declared. In this case, a `Dim` statement is actually not a declaration of a variable but a mere explicit type assignment. It's odd that such a statement may exist in a nested scope; but it'd be even more odd if the variables so type-assigned were scoped to a block while implicitly-typed ones were scoped to a procedure. Also note that in BASICs, `Dim` has executable semantics for arrays. – ach Feb 10 '17 at 13:40