[comp.lang.misc] A comment on language wars.

peter@ficc.ferranti.com (Peter da Silva) (03/05/91)

[ I originally posted an article on this subject about a month ago, but
  it didn't get out of the local area. ]

Periodically language wars spring up in comp.lang.misc when someone enthuses
over some feature of language "A", and how this makes it superior to language
"B". Almost always a supporter of "B" pops up and show how it also can take
advantage of this feature if you try hard enough.

This is trivially true, but meaningless. Any language can be used to implement
an interpreter for any other language, so it can be said that all languages
"have" all features. But what you have to do to the language to do this is
often more trouble than its worth.

The most recent war, over first class functions in C, is a classic example.
No, C functions aren't first class functions in the sense that object oriented
language adherents use the term. So what? The same is true of every other
procedural algol-derived language, including Modula, Euclid, and even ADA
(the language that is to programming as Emacs is to editing). It is not a
sin of C.

In fact, I don't see how a language that isn't interpreted nor object oriented
could be said to have first class functions.

Back to the point: there is nothing wrong with a language not having every
feature of every language under the sun. That way lies ADA and madness.
Don't worry if your favorite language seems to be missing some feature. The
folks who know what they're talking about know better. And the rest of the
readers don't care.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

markf@zurich.ai.mit.edu (Mark Friedman) (03/07/91)

In article <R_V9_AC@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:

   In fact, I don't see how a language that isn't interpreted nor object
   oriented could be said to have first class functions.

Although it is true that most LISP (and Scheme) and purely functional
language implementations have interpretors available, there is no
dependency relation between that fact and the fact that they have
first class functions.  Nor are most of those languages "object
oriented".

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

markf@zurich.ai.mit.edu

peter@ficc.ferranti.com (Peter da Silva) (03/08/91)

In article <MARKF.91Mar6122504@montreux.ai.mit.edu> markf@zurich.ai.mit.edu writes:
> In article <R_V9_AC@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
>    In fact, I don't see how a language that isn't interpreted nor object
>    oriented could be said to have first class functions.

> Although it is true that most LISP (and Scheme) and purely functional
> language implementations have interpretors available, there is no
> dependency relation between that fact and the fact that they have
> first class functions.  Nor are most of those languages "object
> oriented".

I suspect that if you remove the explicit interpreter and examined the
remaining language, I will still be able to point to a part of the
language and say "that's the interpreter!". That will be the part that
takes a closure and executes it. In Forth terms, Lisp has an outer and
an inner interpreter.

You might object that this is a Bernsteinian definition of "interpreter",
but I think it is a distinguishing point between languages that have first
class functions and those that don't.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

sfk@otter.hpl.hp.com (Steve Knight) (03/10/91)

Peter writes:
> I suspect that if you remove the explicit interpreter and examined the
> remaining language, I will still be able to point to a part of the
> language and say "that's the interpreter!". That will be the part that
> takes a closure and executes it. In Forth terms, Lisp has an outer and
> an inner interpreter.

This claim seems to elevate a common implementation practice, that of having 
different run-time formats for procedures built at compile-time and 
procedure built at run-time, to the level of a common "principle".

Although there are many such systems, there are also counter-examples.  One
I am familiar with is the Poplog system, which supports first-class
procedures (in the usual, non-Bernsteinian sense) but has no "interpreted"
form.  Closures are blocks of machine code and are created (by the system)
in the same shape and form as other procedures.  There is no difference
between the invocation of an ordinary procedure and a closure.

The closest I can come to seeing an "interpreter" in the run-time system is
that when procedures are passed as parameters, it is actually pointers to
them that are passed around.  So executing such a procedure involves 
dereferencing a pointer.

The "trick" to avoiding the necessity of an interpreter for a procedure in
a dynamically-typed system is as follows.  Since procedures created at
run-time reside (typically) in the heap, all heap bookkeeping information
(such as type and length) must be placed so as not to interfere with the
procedure or closure format.  In Poplog, this is done by the simple 
expedient of placing it "before" the procedure pointer.  This is just as
suitable for strongly typed languages (but they present slightly fewer
problems).  

I hope this helps to clarify this rather muddy topic.

Steve

billk@hawk.cs.ukans.edu (Bill Kinnersley) (03/10/91)

In article <7HY9P4G@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
: 
: I suspect that if you remove the explicit interpreter and examined the
: remaining language, I will still be able to point to a part of the
: language and say "that's the interpreter!". That will be the part that
: takes a closure and executes it. In Forth terms, Lisp has an outer and
: an inner interpreter.
: 
: You might object that this is a Bernsteinian definition of "interpreter",
: but I think it is a distinguishing point between languages that have first
: class functions and those that don't.
:
Definition of an interpreter: 

   A case statement inside a do loop.

Anything that examines a sequence of data items and makes a series of
decisions based on what it finds there..."That's an interpreter!"

-- 
--Bill Kinnersley
  billk@hawk.cs.ukans.edu
226 Transfer complete.

aipdc@castle.ed.ac.uk (Paul Crowley) (03/11/91)

In article <1991Mar10.145908.10575@hawk.cs.ukans.edu> billk@hawk.cs.ukans.edu (Bill Kinnersley) writes:
>Definition of an interpreter: 
>   A case statement inside a do loop.

Corollary:  Most X programs are interpreters.

I think that some restrictions need to be placed on the way the output
depends on the input. Including a separation between "program" and
"input to program" and some sort of restrictions on the ways the program
may change at run time (basically so that the operative word is "change"
rather than "be created").
                                         ____
\/ o\ Paul Crowley aipdc@uk.ac.ed.castle \  /
/\__/ Part straight. Part gay. All queer. \/

markf@zurich.ai.mit.edu (Mark Friedman) (03/12/91)

In article <7HY9P4G@xds13.ferranti.com> peter@ficc.ferranti.com 
(Peter da Silva) writes:

   In article <MARKF.91Mar6122504@montreux.ai.mit.edu> 
markf@zurich.ai.mit.edu writes:
   > In article <R_V9_AC@xds13.ferranti.com> peter@ficc.ferranti.com 
(Peter da Silva) writes:
   >    In fact, I don't see how a language that isn't interpreted nor object
   >    oriented could be said to have first class functions.

   > Although it is true that most LISP (and Scheme) and purely functional
   > language implementations have interpretors available, there is no
   > dependency relation between that fact and the fact that they have
   > first class functions.  Nor are most of those languages "object
   > oriented".

   I suspect that if you remove the explicit interpreter and examined the
   remaining language, I will still be able to point to a part of the
   language and say "that's the interpreter!".

Why would you say that?

   That will be the part that takes a closure and executes it. In
   Forth terms, Lisp has an outer and an inner interpreter.

Could you explain those terms.

   You might object that this is a Bernsteinian definition of "interpreter",
   but I think it is a distinguishing point between languages that have first
   class functions and those that don't.

Maybe after I understand what you are saying I will object :-)

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

markf@zurich.ai.mit.edu

pcg@test.aber.ac.uk (Piercarlo Antonio Grandi) (03/12/91)

On 11 Mar 91 00:35:47 GMT, aipdc@castle.ed.ac.uk (Paul Crowley) said:

aipdc> In article <1991Mar10.145908.10575@hawk.cs.ukans.edu>
aipdc> billk@hawk.cs.ukans.edu (Bill Kinnersley) writes:

billk> Definition of an interpreter: 
billk>    A case statement inside a do loop.

Quoting myself from long ago: *all* programs are hierarchies of
interpreters. All programs are composed of modules each of which is an
interpreter. An interpreter is composed fo some code (the glue) that
navigates some data structure and examines each of its elements, and of
some code (the library) that provides the ways to handle each element of
that data structure. Either glue or library may be trivial or implicit,
of course.

Important note: the above definition implies that *control* abstraction
is vital to implementing glue, while *data* abstraction is vital to
implementing library functions. OO programming only provides the latter.
Research on control abstraction is very rare.

aipdc> Corollary:  Most X programs are interpreters.

Well, so much so than most other things. Yes, definitely the X server is
an interpreter, or rather, a hierarchy of interpreters. I'd say that X
clients programs are interpreters, even xclock (it interprets just one
instruction).
--
Piercarlo Grandi                   | ARPA: pcg%uk.ac.aber@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@aber.ac.uk

peter@ficc.ferranti.com (Peter da Silva) (03/12/91)

In article <1991Mar10.145908.10575@hawk.cs.ukans.edu> billk@hawk.cs.ukans.edu (Bill Kinnersley) writes:
> Definition of an interpreter: 

>    A case statement inside a do loop.

> Anything that examines a sequence of data items and makes a series of
> decisions based on what it finds there..."That's an interpreter!"

How explicit does the do loop have to be? A jump table that you dive into
on a periodic basis, with a bunch of raw code around it? That's basically
what object-oriented languages use.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

peter@ficc.ferranti.com (Peter da Silva) (03/12/91)

In article <2400032@otter.hpl.hp.com> sfk@otter.hpl.hp.com (Steve Knight) writes:
> The "trick" to avoiding the necessity of an interpreter for a procedure in
> a dynamically-typed system is as follows. [...] In Poplog, this is done by
> the simple expedient of placing [type, lengthe, etc] "before" the procedure
> pointer.

You look up the type and make a decision based on what's there? That's an
interpreter. Forth does the same thing, but puts the type information after
the procedure pointer.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

mrs@netcom.COM (Morgan Schweers) (03/12/91)

In article <9053@castle.ed.ac.uk> aipdc@castle.ed.ac.uk (Paul Crowley) writes:
>In article <1991Mar10.145908.10575@hawk.cs.ukans.edu> billk@hawk.cs.ukans.edu (Bill Kinnersley) writes:
>>Definition of an interpreter: 
>>   A case statement inside a do loop.
>
>Corollary:  Most X programs are interpreters.
>
>I think that some restrictions need to be placed on the way the output
>depends on the input. Including a separation between "program" and
>"input to program" and some sort of restrictions on the ways the program
>may change at run time (basically so that the operative word is "change"
>rather than "be created").

    Why?  At what level of sophistication does a data processor become an
interpreter?  It's my fundamental belief that there IS no difference between
a language 'interpreter' and a data 'processor'.

    Perhaps it's ground that has been trodden over for millenia before I
came here, but is there a reasonable seperating ground between programs
and data?

                                                        --  Morgan Schweers
+-------------------------------------------------------------------------+
|     I *AM* ms@netcom.com and ms@albert.ai.mit.edu.  PLEASE try the first|
| address first.  My employers think I'm just another mindless AI program |
| without opinions...  Please don't try to convince them otherwise!       |
+-------------------------------------------------------------------------+

peter@ficc.ferranti.com (Peter da Silva) (03/12/91)

In article <PCG.91Mar11163937@aberdb.test.aber.ac.uk> pcg@test.aber.ac.uk (Piercarlo Antonio Grandi) writes:
> Quoting myself from long ago: *all* programs are hierarchies of
> interpreters.

You're jumping from languages to programs here. Some languages have an
interpreter effectively built into the core of the language definition
itself. Others require you hand-craft each interpreter you want to build
into a program.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

markf@zurich.ai.mit.edu (Mark Friedman) (03/13/91)

In article <E_-9UU3@xds13.ferranti.com> peter@ficc.ferranti.com 
(Peter da Silva) writes:

   In article <2400032@otter.hpl.hp.com> sfk@otter.hpl.hp.com 
(Steve Knight) writes:

   > The "trick" to avoiding the necessity of an interpreter for a
   > procedure in a dynamically-typed system is as follows. [...] In
   > Poplog, this is done by the simple expedient of placing [type,
   > lengthe, etc] "before" the procedure pointer.

   You look up the type and make a decision based on what's there? That's an
   interpreter. Forth does the same thing, but puts the type information after
   the procedure pointer.

But the type and length information is only necessary for the garbage
collector (which I will admit is an interpreter in a very loose
sense). It is not necessary for the running of the procedure. One
could in principle build a non-gc version of the system which did not
require that information.

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

markf@zurich.ai.mit.edu

peter@ficc.ferranti.com (Peter da Silva) (03/13/91)

In article <MARKF.91Mar12151509@montreux.ai.mit.edu> markf@zurich.ai.mit.edu writes:
> It is not necessary for the running of the procedure. One
> could in principle build a non-gc version of the system which did not
> require that information.

So the procedure is actually built dynamically at runtime?
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

markf@zurich.ai.mit.edu (Mark Friedman) (03/14/91)

In article <-K.9TE3@xds13.ferranti.com> peter@ficc.ferranti.com (Peter
da Silva) writes:

   In article <MARKF.91Mar12151509@montreux.ai.mit.edu>
   markf@zurich.ai.mit.edu writes:

   > It is not necessary for the running of the procedure. One could
   > in principle build a non-gc version of the system which did not
   > require that information.

   So the procedure is actually built dynamically at runtime?

Yes.  But note that the code for the procedure is built once; only the
environment needs to be built at runtime, assuming that any
environment needs to be built at all (the compiler may determine that
some procedures don't need an environment).

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

markf@zurich.ai.mit.edu

peter@ficc.ferranti.com (Peter da Silva) (03/15/91)

In article <MARKF.91Mar13165921@montreux.ai.mit.edu> markf@zurich.ai.mit.edu writes:
> Yes.  But note that the code for the procedure is built once; only the
> environment needs to be built at runtime, assuming that any
> environment needs to be built at all (the compiler may determine that
> some procedures don't need an environment).

OK, so there's where the semantics of the interpreter are implemented, in
the bits and peices that build and maintain these environments without
bothering the programmer.

As an aside, a couple people in mail have assumed that I think this
interpreter is a *bad thing*. Not at all. It's something that has to
be implemented in many programs anyway (think of printf, for example,
or the case statements built by Lex and Yacc), and it opens up all sorts
of possibilities.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

markf@zurich.ai.mit.edu (Mark Friedman) (03/20/91)

In article <8O=9X44@xds13.ferranti.com> peter@ficc.ferranti.com (Peter
da Silva) writes:

   In article <MARKF.91Mar13165921@montreux.ai.mit.edu>
markf@zurich.ai.mit.edu writes:

   > Yes.  But note that the code for the procedure is built once;
   > only the environment needs to be built at runtime, assuming that
   > any environment needs to be built at all (the compiler may
   > determine that some procedures don't need an environment).

   OK, so there's where the semantics of the interpreter are
   implemented, in the bits and peices that build and maintain these
   environments without bothering the programmer.

C'mon.  There is no interpreter hiding in there. My point about
building the code for the peocedure only once had nothing to do with
interpreters. It was just a point about efficiency. The semantics of
Scheme (or most other languages with first class procedures) does not
require an interpreter.  Why do you think first class procedures need
interpreters?

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

markf@zurich.ai.mit.edu