A period of time when some value can be accessed. This begins as the object is created and ends upon some explicit program event, or perhaps only when there remains no way to access the value, in which case it is as if it lasted for ever.
A range of program text where some identifier declaration or binding determines the meaning of an identifier. In the languages we consider this range is contiguous except when the same identifier is used in an inner block which then creates a hole in the scope of the outer binding.
Definite Extent
is when a program event terminates access to some value, most likely reclaiming space used to express the value. Often returning from a routine or method terminates all values that were created ‘automatically’ when the routine was called. The most common ways of accessing these values also disappear at this time but the following C program is invalid for it accesses such a terminated value:
#include <stdio.h>
int * ip;
void routine(){int x = 42; ip = &x;}
int main(){routine(); printf("%d\n", *ip);}
The C programmer is on his honor not to write such programs and the program behavior is erratic. In C malloc and free establish and terminate such values.
Indefinite Extent
is a language style where values remain while there are ways to access them. An implementation of C in such a style would deem the above program value and require that it print 42. Such a compiled program could not use the classic stack logic for the value in ip, which is the address momentarily allocated to the identifier x is invalid as soon as routine returns and its stack frame is deallocated. Scheme, Smalltalk and JavaScript are languages with indefinite extent. Strategically the most significant values that remain after a routine returns are those accessible by routines defined lexically within the called routine. Nested procedures do the heavy lifting in languages such as SmallTalk. Here is a sample SmallTalk program from here:
n := 1.
[ n < 1000 ] whileTrue: [ n := n*2 ].
n → 1024
This program can be transcribed literally to C as follows:
#include <stdio.h>
typedef int t(void);
typedef void a(void);
void whileTrue(t, a); // prototype for system supplied primitive
int main(){
  int n = 1;
  int test(){return n < 1000;}
  void act(){n = n*2;}
  whileTrue(test, act);
  printf("%d\n", n);
  return 0;}

void whileTrue(t tst, a act){ while(tst()) act();}
The above program is not valid C but is valid gcc. Whereas the while construct is primitive in C the whileTrue function is primitive in SmallTalk, or at least provided as a standard function. This example illustrates nested functions but indefinite extent. SmallTalk provides indefinite extent but not gcc.