I know the language exists, but I can't put my finger on it.
dynamic scope and static typing?
Static scope refers to scope of a variable is defined at compile time itself that is when the code is compiled a variable to bounded to some block. 2. Dynamic scope: Dynamic scope refers to scope of a variable is defined at run time rather than at compile time. Perl language allows dynamic scoping.
First, dynamically-typed languages perform type checking at runtime, while statically typed languages perform type checking at compile time.
Statically typed programming languages do type checking at compile-time. Examples: Java, C, C++. Dynamically typed programming languages do type checking at run-time. Examples: Perl, Ruby, Python, PHP, JavaScript.
In most programming languages including C, C++, and Java, variables are always statically (or lexically) scoped i.e., binding of a variable can be determined by program text and is independent of the run-time function call stack.
We can try to reason about what such a language might look like. Obviously something like this (using a C-like syntax for demonstration purposes) cannot be allowed, or at least not with the obvious meaning:
int x_plus_(int y) {
return x + y; // requires that x have type int
}
int three_plus_(int y) {
double x = 3.0;
return x_plus_(y); // calls x_plus_ when x has type double
}
So, how to avoid this?
I can think of a few approaches offhand:
Commenters above mention that Fortran pre-'77 had this behavior. That worked because a variable's name determined its type; a function like x_plus_
above would be illegal, because x
could never have an integer type. (And likewise one like three_plus_
, for that matter, because y
would have the same restriction.) Integer variables had to have names beginning with i
, j
, k
, l
, m
, or n
.
Perl uses syntax to distinguish a few broad categories of variables, namely scalars vs. arrays (regular arrays) vs. hashes (associative arrays). Variables belonging to the different categories can have the exact same name, because the syntax distinguishes which one is meant. For example, the expression foo $foo, $foo[0], $foo{'foo'}
involves the function foo
, the scalar $foo
, the array @foo
($foo[0]
being the first element of @foo
), and the hash %foo
($foo{'foo'}
being the value in %foo
corresponding to the key 'foo'
). Now, to be quite clear, Perl is not statically typed, because there are many different scalar types, and these are types not distinguished syntactically. (In particular: all references are scalars, even references to functions or arrays or hashes. So if you use the syntax to dereference a reference to an array, Perl has to check at runtime to see if the value really is an array-reference.) But this same approach could be used for a bona fide type system, especially if the type system were a very simple one. With that approach, the x_plus_
method would be using an x
of type int
, and would completely ignore the x
declared by three_plus_
. (Instead, it would use an x
of type int
that had to be provided from whatever scope called three_plus_
.) This could either require some type annotations not included above, or it could use some form of type inference.
A function's signature could indicate the non-local variables it uses, and their expected types. In the above example, x_plus_
would have the signature "takes one argument of type int
; uses a calling-scope x
of type int
; returns a value of type int
". Then, just like how a function that calls x_plus_
would have to pass in an argument of type int
, it would also have to provide a variable named x
of type int
— either by declaring it itself, or by inheriting that part of the type-signature (since calling x_plus_
is equivalent to using an x
of type int
) and propagating this requirement up to its callers. With this approach, the three_plus_
function above would be illegal, because it would violate the signature of the x_plus_
method it invokes — just the same as if it tried to pass a double
as its argument.
The above could just have "undefined behavior"; the compiler wouldn't have to explicitly detect and reject it, but the spec wouldn't impose any particular requirements on how it had to handle it. It would be the responsibility of programmers to ensure that they never invoke a function with incorrectly-typed non-local variables.
Your professor was presumably thinking of #1, since pre-'77 Fortran was an actual real-world language with this property. But the other approaches are interesting to think about. :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With