dlocals etc. 
Author Message
 dlocals etc.

Shallow binding of POP-2 variables arose because the 4130 only had one
index register which we needed to use as a stack pointer, since that
provided a general low-space-overhead way of calling functions in what was
a modified functional language. This always appeared as the wrong way of
doing things, since the lambda calculus calls for lexical binding, but was
justified on the grounds that existing lexical binding techniques (as
embodied in Algol) were also wrong, since they didn't provide the
possibility of returning a function as a result of a function. We were of
course aware of the debugging advantages of having part of the environment
available for very little cost.

However the price of dynamic binding became very obvious when we
implemented continuations (done by Ray Dunn in a weekend...) since the
"state", even of a functional program, was distributed throughout the
machine. Moreover we had to complicate the continuation concept by
introducing a "stack barrier" to give us something like efficiency.
To this day we can't compete with Scheme and JNML in generating
light weight continuations.

My own practice these days is to avoid any dlocals in code I actually
write, by using an extra argument to any function (usually called "Env")
which is a data-structure that bundles up any kind of style switch.

Robin.



Sun, 09 Jul 1995 21:51:04 GMT  
 dlocals etc.

Quote:
Robin Popplestone writes:
> To this day we can't compete with Scheme and JNML in generating
> light weight continuations.

Scheme continuations are not quite the same thing as Pop processes regardless
of issues of dlocalisation.  In particular, Pop processes take copies
of the dynamic environment (i.e. copies the callstack) and Scheme
processes do not.

The upshot of this is that Scheme achieves its lightweight continuations
by forcing all (mutable) variables to be type-3 lexicals.  This is just
shifting the work from one place to another, of course.  It makes good sense
in Scheme because very few variables are mutable.  It makes poor sense in
current day Pop because almost all variables are mutable.

Unfortunately, POP-11 doesn't implement environment copying perfectly.  Type-3
lexicals are not copied -- but shared between different processes.  This
is a known defect in Pop processes.

Steve



Tue, 11 Jul 1995 02:23:20 GMT  
 dlocals etc.

Quote:
> Date: 20 Jan 93 13:51:04 GMT
> Organization: University of Massachusetts, Amherst

> Shallow binding of POP-2 variables arose because the 4130 only had one
> index register which we needed to use as a stack pointer, since that
> provided a general low-space-overhead way of calling functions in what was
> a modified functional language. This always appeared as the wrong way of
> doing things, since the lambda calculus calls for lexical binding, but was
> justified on the grounds that existing lexical binding techniques (as
> embodied in Algol) were also wrong, since they didn't provide the
> possibility of returning a function as a result of a function. We were of
> course aware of the debugging advantages of having part of the environment
> available for very little cost.

It is interesting that Pop-2 and Maclisp both used incremental
compilers rather than interpreters, and both used shallow binding
for dynamically scoped identifiers rather than deep binding. By
contrast Interlisp was interpreted and used deep binding, which
required searching up a list of variable value pairs to get the
value of a variable that was last declared local in some calling
procedure.

It turned out that shallow binding, in which all occurrences of a
particular variable pointed to the same memory location, whose value
had to be saved somewhere on entry to a procedure in which the
variable was local and then copied back on exit had a very nice
property, and I believe this happened entirely by accident rather
than by design.

A really "clean" implementation would have required all local
variables to have their values initialised to some safe default on
procedure entry, e.g. to "undef". Instead, for the sake of
efficiency all the implementations of Pop that I have used employed
shallow binding and always left the old value in the variable on
procedure entry, which speeded up procedure entry, and could
occasionally cause obscure bugs, when people forgot to assign to
local variables and they inherited values from the preceding
procedure activation.

But it also had a very nice side effect, namely that shallow-bound
dynamic variables could be used to produce an "incremented context"
mechanism that was automatically reset on procedure exit.

For example, the Pop-11 pattern matcher keeps a list of variables
whose values have been set in the dynamic variable popmatchvars,
which is local to the matcher and also has the empty list as its
global value. This means that inside a recursive call of the
matcher the previously bound variables are already available, and if
new bindings are set, they can be "pushed" onto the front of the
list, e.g. using

    [^word ^^popmatchvars] -> popmatchvars;

However on exit from the recursive call, popmatchvars will
automatically be re-set to its original value, and this is
guaranteed to happen whether the exit is normal or caused by an
interrupt, or a use of "exitfrom", or suspension of a process, etc.

Similarly, printing routines often need to keep count of the level
of recursion to prevent infinite printing. So it is quite common to
use a variable like

    vars
        printlevel = 0,
        max_printlevel = 5;

    define print_procedure( ..... );
        dlocal printlevel = printlevel + 1;

        if printlevel >= max_printlevel then
            ... print closing bracket and return ....
        else
            print suitable opening bracket
            call print_procedure recursively on the components
                of the structure being printed.

        endif
    enddefine;

Because of the way dynamic locals, declared using dlocal or vars,
work, it is guaranteed that the top level value of the variable will
always be reset when the procedure exits, normally or otherwise.

The alternative to these dynamically scoped uses of printlevel and
popmatchvars (and similar things, like interrupt, cucharout,
prmishap, etc.) would have been to require all these values to be
passed explicitly as extra arguments in any procedure that might
call a procedure that used these values, or else to do what Robin
does, namely:

Quote:
> My own practice these days is to avoid any dlocals in code I actually
> write, by using an extra argument to any function (usually called "Env")
> which is a data-structure that bundles up any kind of style switch.

But of course, you have to keep changing the definition of the
structure Env for different purposes, which can makes reuse of code
difficult. Also when the environment changes you either have to use
dlocal anyway, to ensure that it is automatically reset whenever
procedure exit occurs, or else you have to copy the structure on
entry to any procedure that can change it.

I think dynamic local expressions, of which dynamic local variables
are a special case, handle this rather elegantly, and I see no
reason for avoiding them, provided that their use is disciplined.

It's interesting that these extra mechanisms to ensure automatic
resetting of context are needed only because procedures can exit
abormally. If a simpler control regime were used, and only ordinary
procedure exit were available, then all tidying up and resetting of
context could be done by explicit code at the end of a procedure
definition, and there would be no need for dynamically scoped local
variables.

In relation to some of the earlier discussion in this newsgroup, it
is interesting to note that the dlocal mechanism in pop-11 can be
used with global lexically scoped variables, i.e. file-local
lexicals. This undermined the supposed contrast between dynamic and
lexical scoping, and instead caused John Gibson to introduce the
term "permanent" in contrast with "lexical".

I'll return to that topic in a later posting.

Aaron
--
Aaron Sloman,
School of Computer Science, The University of Birmingham, B15 2TT, England

Phone: +44-(0)21-414-3711       Fax:   +44-(0)21-414-4281



Thu, 13 Jul 1995 11:55:37 GMT  
 dlocals etc.

Quote:

> The upshot of this is that Scheme achieves its lightweight continuations
> by forcing all (mutable) variables to be type-3 lexicals.  This is just
> shifting the work from one place to another, of course.  It makes good sense
> in Scheme because very few variables are mutable.  It makes poor sense in
> current day Pop because almost all variables are mutable.

Pardon my ignorance, Steve, but what do you mean by mutable?

Humbly,

Luc
--
-------------------------------------- -----------------------------------
Luc Beaudoin                          |  School of Computer Science

voice:  +44 (21) 414-4766 or 3743     |  Birmingham B15 2TT, UK



Fri, 14 Jul 1995 02:01:08 GMT  
 dlocals etc.
Luc asks:

Quote:
> Pardon my ignorance, Steve, but what do you mean by mutable?

Allowed to change -- the inverse of constant.  Most variables in Pop
are updated more than once in their dynamic lifetime and are therefore
intrisincally mutable.  Some variables are allowed to change but provably
are never assigned to more than once -- they are potentially mutable but
can be treated as immutable (i.e. constant).

There is an ambiguity over whether (im)mutability just applies to the top-
level of a datastructure or all levels.  e.g. If I write
    constant foo = {'dog'};
then the variable foo is immutable -- it always points to the same
location.  However, its value is mutable. i.e.
    'cat' -> foo(1);
is legal and changes the value of foo.  So the question is whether it is
really proper to talk of foo being immutable when it value can change?  In
Pop, it turns out that the best way to use the term immutable is to only
be concerned with the top-level.  This is because there are so few data
structures in Pop which are non-assignable, the other usage would never
apply.

Hope this helps!

Steve



Fri, 14 Jul 1995 20:02:32 GMT  
 dlocals etc.

Quote:
>A really "clean" implementation would have required all local
>variables to have their values initialised to some safe default on
>procedure entry, e.g. to "undef".

..and to take advantage of internal knowledge of the fact that it doesn't
raises the hackles of anyone concerned about "future release surprise" or
portability!

Quote:
>    define print_procedure( ..... );
>        dlocal printlevel = printlevel + 1;

looks pretty bogus to me.  I've been trying to teach programmers to avoid
this sort of thing for years.  POP-2 was quite clear about it, even though
this code would "work".  The reference manual states that when the extent
of another variable is interrupted "its value is not altered but it cannot
be accessed or changed by assignment."

Quote:
>The alternative to these dynamically scoped uses of printlevel and
>popmatchvars (and similar things, like interrupt, cucharout,
>prmishap, etc.) would have been to require all these values to be
>passed explicitly as extra arguments in any procedure that might
>call a procedure that used these values, or else to do what Robin
>does, namely:

>> My own practice these days is to avoid any dlocals in code I actually
>> write, by using an extra argument to any function (usually called "Env")
>> which is a data-structure that bundles up any kind of style switch.

In 'C' the effect can often be achieved by using a _static_ variable, but
my own technique is to use a pair of functions - the outer function
presents a "clean" interface to the outside world and calls a second
function with all the required extra arguments - it is this second function
that recurses.

So Aaron's example becomes (ha! I'll do it in POP-2ish)

    vars max_printlevel;
    5 -> max_printlevel;

    print_procedure(....)
        aux_print_proc(..... , 1);
    end

    aux_print_proc(..... , printlevel)

        if printlevel >= max_printlevel then
            ... print closing bracket and return ....
        else
            ... print suitable opening bracket ....
            aux_print_proc(whatever tail of structure, printlevel+1);
        close
    end

Now who has a compiler I can syntax check this with!!
--
Ray Dunn at home        |  Beaconsfield, Quebec  |  Phone: (514) 630 3749



Sat, 15 Jul 1995 11:39:34 GMT  
 dlocals etc.

Quote:

>If I write
>    constant foo = {'dog'};
>then the variable foo is immutable -- it always points to the same
>location.  

Unless, of course there is a subsequent line such as:
        constant foo = ['something else'];

Since you can easily redefine constants in this way, even these are mutable.

Using sysprotect("foo"); would provide an extra level of immutability,
but even then that does not prevent a subsequent sysunprotect("foo");
from making foo vulnerable again. I suppose ultimately, immutability
is a matter of degree, which depends on the amount of effort required
to change the value to something else. The only totally unalterable
variables are those stored in ROM!
--


Department of Computing Mathematics
University of Wales College of Cardiff                          __o
PO Box 916                                                      \<,  
CARDIFF    CF2 4YN                         ___________________()/ ()___  



Sun, 16 Jul 1995 00:03:19 GMT  
 dlocals etc.

Quote:

>     constant foo = {'dog'};
> then the variable foo is immutable -- it always points to the same

Ok, I thought there might have been some other technical meaning. (I
also thought we might want to say that constants aren't variables
since they're not variable (at the top level)! But given your
message and help files, I see that the usage is to refer to
constants as variables. Fair enough.)

Luc
--
-------------------------------------- -----------------------------------
Luc Beaudoin                          |  School of Computer Science

voice:  +44 (21) 414-4766 or 3743     |  Birmingham B15 2TT, UK



Sun, 16 Jul 1995 04:55:24 GMT  
 dlocals etc.

The discussion about definable constants (or not) reminds me of the
similar situation in Pepper. I intend Pepper to be used interactively,
in the same way as Pop, and yet wish to avoid some of the strange effects
(such as redefinable constants).

The Pepper solution is this. First, there are two kinds of declarations,
``val'' and ``var''. Identifiers declared by ``val'' are not assignable
(the declaration initialises them), while those declared by ``val'' are.

[Quickly scanning the Pepper code to hand, I see more than 750 ``val''s
and less than 250 ``var''s. These figures are distored in favour of
``var'' (yes, in *favour* of *vaR*) because (a) var's tend to appear
at top level, (b) there are two very similar large programs in my
sample, which both (c) use var's to cope with the bootstrap compilers
inability to have top-level val declarations with run-time initialisation
values.]

Names are redefinable (``fluid'') or not (``static''; these terms are
not fixed, not least because the compiler doesn't do this yet!).
Redefinable constants (val's) are just like variables, except for being
unassignable; that is, when they are redefined, everyone sees the new
value (unlike Pop constants). Unredefinable constants get their values
compiled into the code.

Qualifiers on declarations allow the programmer to choose between
re- and unre- definable. The default in interactive use is re-; for
batch compilation, it is unre-. (Just as well, because the bootstrap
compiler doesn't allow any sort of redefinition.)

Thus you can never over-ride a static val's value, and a fluid val's
value is subject to change without notice. There will be a way to
pick the default qualifier, so you can make an interactive compilation
get you static val's. The effect of Pop's ``protected'' will probably
be obtained by the as-yet-vague module system.

--

Regards | "Always code as if the guy who ends up maintaining your code will be
Kers.   | a {*filter*} psychopath who knows where you live." - John F. Woods



Sun, 16 Jul 1995 22:23:26 GMT  
 dlocals etc.

Quote:

> Date: 26 Jan 93 03:39:34 GMT
> Organization: Not Philips.


[AS]
> >A really "clean" implementation would have required all local
> >variables to have their values initialised to some safe default on
> >procedure entry, e.g. to "undef".

[RD]

Quote:
> ...and to take advantage of internal knowledge of the fact that it doesn't
> raises the hackles of anyone concerned about "future release surprise" or
> portability!

[AS]
But note that this has been a dependable feature of every Pop
implementation for at least 22 years. Suppose it were written into
the manual, would you still object to its use?

In fact, I think that it is an essential part of the dlocal
mechanism that you can access the previous value as well as being
able to update it. E.g. you can do things like

    dlocal hd(list);

        hd(list) + 1 -> hd(list);

in a procedure, with a *guarantee* that on exit from that procedure,
whether normal or abnormal, the previous value stored in the head of
the list will be reset. It would be illogical to disallow the
special case of a value stored in a variable.

Of course a defender of pure functional programming would disallow
the updating of a datastructure in any case, and the argument would
change (which is I think Robin's position, if I've understood it.)

Ray objected to my example use of this facility:

[AS]

Quote:
> >    define print_procedure( ..... );
> >        dlocal printlevel = printlevel + 1;

[RD]
> looks pretty bogus to me.  I've been trying to teach programmers to avoid
> this sort of thing for years.  POP-2 was quite clear about it, even though
> this code would "work".  The reference manual states that when the extent
> of another variable is interrupted "its value is not altered but it cannot
> be accessed or changed by assignment."

[AS]
Well, what I am claiming (if I understand the terminology correctly)
is that allowing the value from the previous context to be accessed,
but not altered, before the first assignment in the new context, is
a very useful extension to the expressive power of the language.

[AS]

Quote:
>The alternative to these dynamically scoped uses of printlevel and
> >popmatchvars (and similar things, like interrupt, cucharout,
> >prmishap, etc.) would have been to require all these values to be
> >passed explicitly as extra arguments in any procedure that might
> >call a procedure that used these values, ....
> > .....

Which is what Ray recommends:
[RD]

Quote:
> In 'C' the effect can often be achieved by using a _static_ variable, but
> my own technique is to use a pair of functions - the outer function
> presents a "clean" interface to the outside world and calls a second
> function with all the required extra arguments - it is this second function
> that recurses.

> So Aaron's example becomes (ha! I'll do it in POP-2ish)

>     vars max_printlevel;
>     5 -> max_printlevel;

>     print_procedure(....)
>         aux_print_proc(..... , 1);
>     end

>     aux_print_proc(..... , printlevel)

>         if printlevel >= max_printlevel then
>             ... print closing bracket and return ....
>         else
>             ... print suitable opening bracket ....
>             aux_print_proc(whatever tail of structure, printlevel+1);
>         close
>     end

Note that this solution works if all printing is done via one
procedure, which used to be the case in POP2, but is no longer the
case in Pop-11, where different data-types have their own
class_print procedures, a bit like an object oriented system where
each class has its own methods (as is the case in Steve Knight's new
objectclass extension to Pop-11) (adverti{*filter*}t).

Extracts from REF PRINT in the online manual follow:

-------------------------------------------------------------------
The basic printing procedure in POPLOG is -sys_syspr-, which prints  any
item in its  standard format. While  this can be  called directly if  so
desired, the  system  additionally  provides  the  procedures  -pr-  and
-syspr- as a  two-stage mechanism  for printing  objects in  a way  that
allows dynamic redefinition of the actual printing procedures used.

    The mechanism  is based  on the  convention that  programs  normally
print objects  using the  variable procedure  -pr-, which  in the  first
place, can be redefined in any  desired way. However, the default  value
of the variable -pr- is the procedure -syspr-, which prints an object by
calling its -class_print- procedure with the object as argument (see REF
*KEYS); thus in the second place, the printing of individual data  types
can be altered by redefining their -class_print- procedures. Because the
default -class_print- of any type is -sys_syspr-, (printing in  standard
format), the normal sequence of events is therefore:

        pr(ITEM)
                ---> syspr(ITEM)
                            ---> class_print(datakey(ITEM))(ITEM)
                                        ---> sys_syspr(ITEM)

    It is important to note, however, that to enable the redefinition of
printing procedures for given  data types to take  effect at any  level,
-sys_syspr- always calls -pr-  to print the  sub-components of any  data
structure (i.e. list,  vector and  record elements,  etc). (Thus  saying
that -sys_syspr-  'prints  any  item  in its  standard  format'  is  not
strictly correct, since  the printing of  sub-components will depend  on
-pr-. A COMPLETELY standard printing procedure would be

        define pr_standard(ITEM)
            lvars ITEM;
            dlocal pr = sys_syspr;
            sys_syspr(ITEM)
        enddefine;

i.e. one that locally redefines -pr- to be -sys_syspr-.)

pr(ITEM)                                            [procedure variable]
        This variable procedure is conventionally used by all procedures
        in the  system  which  print something;  its  default  value  is
        -syspr-.

syspr(ITEM)                                                  [procedure]
        This procedure does

                class_print(datakey(ITEM))(ITEM)

        i.e. apply the -class_print- of the  data type of ITEM to  ITEM.
        The default -class_print- of every data type is -sys_syspr-, but
        this can be redefined as desired -- see REF *KEYS.
-------------------------------------------------------------------

This means that for Ray's mechanism to work, every class_print
procedure would have to take an extra argument, namely the
printlevel, and every other procedure that did any printing would
have to be given a printlevel as part of its input, and then it
would pass on the incremented value to the next printing function it
called. So the above definitions would have to replaced with
something like:

pr(ITEM,INTEGER)
        This variable procedure is conventionally used by all procedures
        in the  system  which  print something;  its  default  value  is
        -syspr-.

syspr(ITEM,INTEGER)
        This procedure does

                class_print(datakey(ITEM))(ITEM,INTEGER)

        unless INTEGER exceeds max_printlevel

I.e. every class_print procedure would need an extra input.

(Incidentally, for printing one normally needs at least two control
variables, one for depth of nesting and one for length of tails,
and Poplog Pop-11 is wrong to have only one variable for nesting,
namely pop_pr_level)

I suspect that Ray's type of solution would be acceptable for
printing, simply because once you get into any printing procedure
you stay within printing procedures which call other printing
procedures explicitly or implicitly (e.g. via class_print), so
there's no real difficulty in passing on the extra parameters.

More generally, however, there are cases where there's a context,
e.g. a database of some kind that's extended by a hypothetical
action, and various different procedures can get called which only
*indirectly*, via several levels of procedure calling eventually
invoke the procedure that further extends the context. For that
situation the extra parameter would have to be supplied to lots of
procedures that do nothing with it except pass it on. If you have
lots of such parameters (cucharout, prmishap, database, interrupt,
etc. etc.) it gets messy. Then Robin's solution of providing a
single environment that's passed on by every procedure looks like
the only attractive solution.

What that amounts to is abandoning global variables that can be
changed locally. It's a consistent way to do things, and maybe has
some nice properties. I suspect that for a large team of programmers
developing a suite of interrelated programs that can call one
another recursively it may be less convenient and less efficient
than using global variables that are dynamically scoped using
dlocal. But I don't know.

[RD]

Quote:
> Now who has a compiler I can syntax check this with!!

A nice project for a student learning to use Pop-11's compiler
development tools?

Aaron
--
--
Aaron Sloman,
School of Computer Science, The University of Birmingham, B15 2TT, England

Phone: +44-(0)21-414-3711       Fax:   +44-(0)21-414-4281



Sun, 16 Jul 1995 18:08:43 GMT  
 dlocals etc.

Quote:

> Date: 26 Jan 93 16:03:19 GMT
> Organization: University of Wales College of Cardiff


[sfk]
> >If I write
> >    constant foo = {'dog'};
> >then the variable foo is immutable -- it always points to the same
> >location.

[db]

Quote:
> Unless, of course there is a subsequent line such as:
>    constant foo = ['something else'];

> Since you can easily redefine constants in this way, even these are mutable.

That's correct, but I suspect that what Steve meant is illustrated
by the following example.

    constant x = 99;

    define test();
        x =>
    enddefine;

    test();
    ** 99

    constant x = 77;

    x =>
    ** 77

    test();
    ** 99

    define newtest();
        x =>
    enddefine;

    newtest();
    ** 77

I.e. any code compiled between the two constant declarations of x
that uses x, does not access its value via the variable x (i.e. a
location in memory associated with the identifier "x"). Instead the
use of x compiles to code that points directly to whatever was
assigned to x. So it is as if the value of the constant were
actually used throughout instead of the variable name "x". When you
redeclare the constant and give it a new value, subsequent code
will use the new value.

Allowing this redeclaration and reassignment to a "constant" is of
course questionable, and can lead to errors if identifier names are
not chosen carefully to avoid clashes. But in an interactive
development environment designed to support rapid prototyping and
testing, it is necessary to allow a file including constant
declarations to be recompiled and for the constant value to be
changed. The simplest way to do this is to allow a new constant
declaration to permit one new assignment to the variable.

(This was previously not permitted and required the identifier to be
cancelled in between recompiling the file. This was often extremely
inconvenient. Instead the new constant declaration effectively
cancels the old constant identifier and starts a new one.)

Regarding Luc's point about the use of the word "variable" to
refer to constants: it is in a sense a variable, whose value is
changeable, as shown above, but between changes all compiled uses
are constant, and moreover, between re-declarations attempts to
compile code that assigns to the variable will produce an error;

    define test3();
        66 -> x;
    ;;; MISHAP - COMPILING ASSIGNMENT TO CONSTANT
    ;;; INVOLVING:  x

Maybe instead of the word "constant" the declaration should have
taken the form
    compile_as_constant x = 99;

In fact, I tend to refer to x as an identifier rather than as a
variable, if it's a constant! In Pop-11 it is strictly the
identifier that has the syntactic property of compiling as a
constant and preventing reassignments. For constants we have the
following entities:

    <word> -->--  <identifier> -->-- <value>

for non-constants we have

    <word> -->--  <identifier> -->-- <variable> -->-- <value>

For compiled code involve constants we have

    <code> -->-- <value>

For compiled code involving variables we have

    <code> -->-- <variable> -->-- <value>

where <variable> is a location in memory associated with the
<identifier>, to which code involving the identifier refers. For
constants there is no such location accessible by compiled code.
It's only accessible during compilation.

Incidentally, "lconstant" (for lexically scoped constant
identifiers) is the same except that you cannot have two lconstant
declarations for the same identifier in the same lexical scope;

    define test4();
        lconstant x = 77;
        x =>
        lconstant x = 88;
    ;;; MISHAP - ILLEGAL ASSIGNMENT TO LCONSTANT
    ;;; INVOLVING:  x

Aaron
--
--
Aaron Sloman,
School of Computer Science, The University of Birmingham, B15 2TT, England

Phone: +44-(0)21-414-3711       Fax:   +44-(0)21-414-4281



Sun, 16 Jul 1995 18:31:09 GMT  
 dlocals etc.

... quite a lot, actually.

   The Pepper solution is this. First, there are two kinds of declarations,
   ``val'' and ``var''. Identifiers declared by ``val'' are not assignable
   (the declaration initialises them), while those declared by ``val'' are.
                                                                 ^
Of course, you will have noticed that I should have said ``var'' | ...

   [Quickly scanning the Pepper code to hand, I see more than 750 ``val''s
   and less than 250 ``var''s. ...]

I realised (thanks, Steve) that I had completely forgotten about for
loop identifiers and procedure parameters! There were 92 for loops
(each contributing one val identifier) and about 1170 parameters,
of which about 20 were var's (by default, they'd be val's). That
brings to total to approximately 1900 val's versus 270 var's, so
val's make up about 7/8ths of the variables in my code.

The numbers are only approximate, because I used grep, tr, and wc
to do my counting. But they shouldn't be too far off. Perhaps one
day I'll hack the compiler to do the stats for me.
--

Regards,    | "You're better off  not dreaming of  the things to come;
Kers.       | Dreams  are always ending  far too soon." - Caravan.



Mon, 17 Jul 1995 21:42:21 GMT  
 
 [ 19 post ]  Go to page: [1] [2]

 Relevant Pages 

1. puzzle about dlocal and input locals

2. conditional version of dlocal

3. dlocals

4. Algorithm etc etc

5. Overloading and / or / = / etc etc

6. Demos, PMode, Graphics, Docs, Tutorials, etc, etc

7. Demos, PMode, Graphics, Docs, Tutorials, etc, etc

8. Embedding Python, PyImport_* etc etc...

9. Is there a standard module library function to access /etc/passwd or /etc/group

10. TOUPPER etc on DEC/VAXstation etc

11. Complicated problems with interpreters, forking, etc. etc. etc...

12. unit conversions, etc. etc.

 

 
Powered by phpBB® Forum Software