home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.pop
- Path: sparky!uunet!inmos!fulcrum!bham!bhamcs!axs
- From: axs@cs.bham.ac.uk (Aaron Sloman)
- Subject: Re: dlocals etc. (and shallow binding)
- Message-ID: <C1IC6K.F2H@cs.bham.ac.uk>
- Sender: news@cs.bham.ac.uk
- Nntp-Posting-Host: emotsun
- Organization: School of Computer Science, University of Birmingham, UK
- References: <58946@dime.cs.umass.edu> <C1CAwq.8up@cs.bham.ac.uk> <1993Jan26.033934.12517@philmtl.philips.ca>
- Date: Wed, 27 Jan 1993 10:08:43 GMT
- Lines: 220
-
- ray@philmtl.philips.ca (Ray Dunn) writes:
-
- > Date: 26 Jan 93 03:39:34 GMT
- > Organization: Not Philips.
- >
- > In refd article, axs@cs.bham.ac.uk (Aaron Sloman) writes:
- [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]
- > ...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]
- > > 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]
- >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]
- > 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) (advertisement).
-
- 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]
- > 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
- EMAIL A.Sloman@cs.bham.ac.uk OR A.Sloman@bham.ac.uk
- Phone: +44-(0)21-414-3711 Fax: +44-(0)21-414-4281
-