How is COBOL's scope defined? Is it statically scoped?
Cobol has compile time binding for variables, sometimes called static scope.
Within that, Cobol supports several layers of scope within programs:
"External" variables are the equivilent of a Fortran or assembler common section, they are truly global.
"Global Program Scope" variables declared in working storage as global are visible to the entire program in which they are declared AND in all nested subprograms contained in that program.
"Program Scope" variables declared in working storage are visible to the entire program in which they are declared.
"Program Scope" variables declared in local storage are visible to the entire program in which they are declared, but are deleted and reinitialized on every invocation. Think thread scoped, sorta.
"Nested Program Scope" Cobol does not distinguish between programs and functions/procedures, its equvilent of a procedure or function is called a program. An infinite number of programs can be contained within a program, and the variables of each are visible only within the scope of that individual program. You could think of this as function/procedure scope.
The OO extensions that many vendors have, and the 2002 standard, defines the traditional public/protected/private object scope and method scope.
"Cobol" is as old as Radar, Laser, and Scuba, can we please stop acronymizing it?
All variables in a COBOL program are globally scoped. In fact, there are no "scopes" (in traditional COBOL, I'm not messing with OO extensions), but just "modules" or "programs".
Intermodule communication is done via the Linkage Section (usually passed by ref), and also all variables there are visible from the called module.
COBOL uses static (lexical) scope (as do C, C++, Java and Pascal). Dynamic scope is not all that common in the programming world. I think some versions of Lisp and SNOBOL used dynamic scope.
If you are interested in understanding scope with respect to programming languages you should review this document
Related
I've read the spec but I'm still confused how my class differs from [our] class. What are differences and when to use which?
The my scope declarator implies lexical scoping: following its declaration, the symbol is visible to the code within the current set of curly braces. We thus tend to call the region within a pair of curly braces a "lexical scope". For example:
sub foo($p) {
# say $var; # Would be a compile time error, it's not declared yet
my $var = 1;
if $p {
$var += 41; # Inner scope, $var is visible
}
return $var; # Same scope that it was declared in, $var is visible
}
# say $var; # $var is no longer available, the scope ended
Since the variable's visibility is directly associated with its location in the code, lexical scope is really helpful in being able to reason about programs. This is true for:
The programmer (both for their own reasoning about the program, but also because more errors can be detected and reported when things have lexical scope)
The compiler (lexical scoping permits easier and better optimization)
Tools such as IDEs (analyzing and reasoning about things with lexical scope is vastly more tractable)
Early on in the design process of the language that would become Raku, subroutines did not default to having lexical scope (and had our scope like in Perl), however it was realized that lexical scope is a better default. Making subroutine calls always try to resolve a symbol with lexical scope meant it was possible to report undeclared subroutines at compile time. Furthermore, the set of symbols in lexical scope is fixed at compile time, and in the case of declarative constructs like subroutines, the routine is bound to that symbol in a readonly manner. This also allows things like compile-time resolution of multiple dispatch, compile-time argument checking, and so forth. It is likely that future versions of the Raku language will specify an increasing number of compile-time checks on lexically scoped program elements.
So if lexical scoping is so good, why does our (also known as package) scope exist? In short, because:
Sometimes we want to share things more widely than within a given lexical scope. We could just declare everything lexical and then mark things we want to share with is export, but..
Once we get to the point of using a lot of different libraries, having everything try to export things into the single lexical scope of the consumer would likely lead to a lot of conflicts
Packages allow namespacing of symbols. For example, if I want to use the Cro clients for both HTTP and WebSockets in the same code, I can happily use both, and refer to them as Cro::HTTP::Client and Cro::WebSocket::Client respectively.
Packages are introduced by package declarators, such as class, module, grammar, and (with caveats) role. An our declaration will make an installation in the enclosing package construct.
These packages ultimately exist within a top-level package named GLOBAL - which is fitting, since they are effectively globally visible. If we declare an our-scoped variable, it is thus a global variable (albeit hopefully a namespaced one), about which enough has been written that we know we should pause for thought and wonder if a global variable is the best API decision (because, ultimately, everything that ends up visible via GLOBAL is an API decision).
Where things do get a bit blurry, however, is that we can have lexical packages. These are packages that do not get installed in GLOBAL. I find these extremely useful when doing OO programming. For example, I might have:
# This class that ends up in GLOBAL...
class Cro::HTTP::Client {
# Lexically scoped classes, which are marked `my` and thus hidden
# implementation details. This means I can refactor them however I
# want, and never have to worry about downstream fallout!
my class HTTP1Pipeline {
# Implementation...
}
my class HTTP2Pipeline {
# Implementation...
}
# Implementation...
}
Lexical packages can also be nested and contain our-scoped variables, however don't end up being globally visible (unless we somehow choose to leak them out).
Different Raku program elements have been ascribed a default scope:
Subroutines default to lexical (my) scope
Methods default to has scope (only visible through a method dispatch)
Type (class, role, grammar, subset) and module declarations default to package (our) scope
Constants and enumerations default to package (our) scope
Effectively, things that are most often there to be shared default to package scope, and the rest do not. (Variables do force us to pick a scope explicitly, however the most common choice is also the shortest one to type.)
Personally, I'm hesitant to make a thing more visible than the language defaults, however I'll often make them less visible (for example, my on constants that are for internal use, and on classes that I'm using to structure implementation details). When I could do something by exposing an our-scoped variable in a globally visible package, I'll still often prefer to make it my-scoped and provide a sub (exported) or method (visible by virtue of being on a package-scoped class) to control access to it, to buy myself some flexibility in the future. I figure it's OK to make wrong choices now if I've given myself space to make them righter in the future without inconveniencing anyone. :-)
In summary:
Use my scope for everything that's an implementation detail
Also use my scope for things that you plan to export, but remember exporting puts symbols into the single lexical scope of the consumer and risks name clashes, so be thoughtful about exporting particularly generic names
Use our for things that are there to be shared, and when its desired to use namespacing to avoid clashes
The elements we'd most want to share default to our scope anyway, so explicitly writing our should give pause for thought
As with variables, my binds a name lexically, whereas our additionally creates an entry in the surrounding package.
module M {
our class Foo {}
class Bar {} # same as above, really
my class Baz {}
}
say M::Foo; # ok
say M::Bar; # still ok
say M::Baz; # BOOM!
Use my for classes internal to your module. You can of course still make such local symbols available to importing code by marking them is export.
The my vs our distinction is mainly relevant when generating the symbol table. For example:
my $a; # Create symbol <$a> at top level
package Foo { # Create symbol <Foo> at top level
my $b; # Create symbol <$b> in Foo scope
our $c; # Create symbol <$c> in Foo scope
} # and <Foo::<$c>> at top level
In practice this means that anything that is our scoped is readily shared to the outside world by prefixing the package identifier ($Foo::c or Foo::<$c> are synonymous), and anything that is my scoped is not readily available — although you can certainly provide access to it via, e.g., getter subs.
Most of the time you'll want to use my. Most variables just belong to their current scope, and no one has any business peaking in. But our can be useful in some cases:
constants that don't poison the symbol table (this is why, actually, using constant implies an our scope). So you can make a more C-style enum/constants by using package Colors { constant red = 1; constant blue = 2; } and then referencing them as Colors::red
classes or subs that should be accessible but needn't be exported (or shouldn't be because overlapping symbols with builtins or other modules). Exporting symbols can be great, but sometimes it's also nice to have the package/module namespace to remind you what stuff goes with. As such, it's also a nice way to manage options at runtime via subs: CoolModule::set-preferences( ... ). (although dynamic variables can be used to nice effect here as well).
I'm sure others will comment with other times the our scope is useful, but these are the ones from my own experience.
everyone what is the difference between those 4 terms, can You give please examples?
Static and dynamic are jargon words that refer to the point in time at which some programming element is resolved. Static indicates that resolution takes place at the time a program is constructed. Dynamic indicates that resolution takes place at the time a program is run.
Static and Dynamic Typing
Typing refers to changes in program structure that are due to the differences between data values: integers, characters, floating point numbers, strings, objects and so on. These differences can have many effects, for example:
memory layout (e.g. 4 bytes for an int, 8 bytes for a double, more for an object)
instructions executed (e.g. primitive operations to add small integers, library calls to add large ones)
program flow (simple subroutine calling conventions versus hash-dispatch for multi-methods)
Static typing means that the executable form of a program generated at build time will vary depending upon the types of data values found in the program. Dynamic typing means that the generated code will always be the same, irrespective of type -- any differences in execution will be determined at run-time.
Note that few real systems are either purely one or the other, it is just a question of which is the preferred strategy.
Static and Dynamic Binding
Binding refers to the association of names in program text to the storage locations to which they refer. In static binding, this association is predetermined at build time. With dynamic binding, this association is not determined until run-time.
Truly static binding is almost extinct. Earlier assemblers and FORTRAN, for example, would completely precompute the exact memory location of all variables and subroutine locations. This situation did not last long, with the introduction of stack and heap allocation for variables and dynamically-loaded libraries for subroutines.
So one must take some liberty with the definitions. It is the spirit of the concept that counts here: statically bound programs precompute as much as possible about storage layout as is practical in a modern virtual memory, garbage collected, separately compiled application. Dynamically bound programs wait as late as possible.
An example might help. If I attempt to invoke a method MyClass.foo(), a static-binding system will verify at build time that there is a class called MyClass and that class has a method called foo. A dynamic-binding system will wait until run-time to see whether either exists.
Contrasts
The main strength of static strategies is that the program translator is much more aware of the programmer's intent. This makes it easier to:
catch many common errors early, during the build phase
build refactoring tools
incur a significant amount of the computational cost required to determine the executable form of the program only once, at build time
The main strength of dynamic strategies is that they are much easier to implement, meaning that:
a working dynamic environment can be created at a fraction of the cost of a static one
it is easier to add language features that might be very challenging to check statically
it is easier to handle situations that require self-modifying code
Typing - refers to variable tyes and if variables are allowed to change type during program execution
http://en.wikipedia.org/wiki/Type_system#Type_checking
Binding - this, as you can read below can refer to variable binding, or library binding
http://en.wikipedia.org/wiki/Binding_%28computer_science%29#Language_or_Name_binding
Due to a wave of criticism to use Global Vars in my Java post, I want to use a language without global vars. One suggestion per answer, thank you.
If you want to avoid side-effects you can use one of the pure functional programming languages like haskell (or erlang or ...), which have only constants. But be prepared for a completely different kind of programming compared to the imperative programming style.
I'm not sure if you literally mean no global variables (values that change), or if you also want to rule out global constants (values that don't change). Haskell is one such language that doesn't have global variables, although it does have global constants (in the form of parameterless functions, essentially). In Haskell, if you want to emulate global state, you have to pass your "global" variables into each function you call. A better description is available from the HaskellWiki.
If you don't want global variables then don't use them. I'm don't see why finding a language that doesn't support them would offer any value. You're dealing with a question of scope. Make your variables exist in the lowest scope possible and you'll be fine. There is no language that doesn't have a global scope.
Java (and similar OOP-languages) doesn't have really global variables, all variables are tied to an instance or a class. But I think you want also outrule the 'simulated' global variables (public fields with the only reason to be accessed from the outside). I don't think any of the popular languages don't allow this, but more uncommon language-concepts may have ways to avoid such things.
Well, I read that Graal is a functional programming language without variables, so I guess that might qualify.
I believe Eiffel doesn't use global variables but that isn't a serious criterion
of whether to use a language or not.
Newspeak has no global namespace and so no global variables, everything is late bound, I think other langages in the BETA family have the same property.
https://en.wikipedia.org/wiki/Newspeak_(programming_language)
The latest one entering this club would be V.
I'm wondering if anyone if aware of a language that has support for variables (that could be considered 'global'), and subroutines (functions), but without a concept of parameter passing, local scope, etc. Something where every subroutine has access to every global variable, and only global variables.
BASIC and assembly come immediately to mind.
Of course, this is not construed as a feature. That's why we invent conventions for which global variables should be used for parameter passing.
As the title suggests I am wondering what the relationship between these two programming concepts are. Does a certain type system (static / dynamic) lend itself to a certain type of scoping (lexical / dynamic), or are these independent language choices?
Static typing doesn't work all that well with dynamic scoping since the variable binding is resolved at runtime. It's possible but it would be unwieldy, since the type system would have to type free variables somehow, probably by examining bound ones. Basically, you couldn't declare two different variables of the same name but different type. Strong and weak typing will also come into play. I'm still pondering what form a static, weakly typed, dynamically scoped language might take, assuming it's possible.
Lexical scoping is paired with both static and dynamic typing.