[comp.lang.misc] What ``first-class'' means in comp.lang.misc

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/09/91)

There is certainly some confusion here over what ``first-class'' means.
Here's a summary of what several people have said about first-class
objects in recent discussions here.

Three people---Dave Gudeman, Norman Graham, and I---seem to agree on a
single definition of first-class. Among other things, the definition
implies that function pointers in C and structures in ANSI C are
first-class, and that structures in pre-ANSI C are not first-class.

All the other definitions disagree with each other on some particular.
Must it be possible to return first-class objects from functions? Not if
you believe Dybvig (as quoted by Dickey). Must it be possible to pass
them as arguments? Not if you believe Clinger (as quoted by Ozan). Are
C's integers first-class? Only if you believe Lennart.

Without further ado, here's the complete summary. I think the only
statement we can all agree with is Lennart's claim that ``first-class''
has several definitions.

In <304@coatimundi.cs.arizona.edu> Dave Gudeman defines ``first-class''
as follows: ``The type of the object in question can be passed as an
argument to procedures and returned from procedures as a result. In
procedural languages like C, it also means that you can assign the
values to variables.'' He says that C's function pointers are
first-class. (Just in case somebody's been asleep through this
discussion: This is the same definition that I'm familiar with, and I
agree with the conclusion.)

In <1990Dec19.222059.6878@mathrt0.math.chalmers.se> Lennart Augustsson
made a claim that, if read literally, implies that first-class functions
must be composable.

In <1990Dec29.101233.1894@mathrt0.math.chalmers.se> Lennart says that
``first-class'' has several definitions. One of them, he says, is this:
``For a type to be first class it should be possible to do the same
things with its objects as with objects of other types, such as
integers.'' He says that this includes not only argument passing but
``be expressible without giving it a name.'' He says that (ANSI) C's
structures are not first-class, but that gcc's structures are, because
gcc lets you write unnamed struct values.

In <1991Jan7.185658.20240@basho.uucp> John Lacey says that
``first-class'' implies having ``the right to be anonymous.''

In <20021@yunexus.YorkU.CA> Ozan Yigit quotes William Clinger. Clinger
doesn't actually claim to define ``first-class'' in the quoted material,
but Ozan appears to believe that the properties listed form a
definition: having the right to remain anonymous, having an identity
independent of any names by which the object may be known, being
storable in variables and in data structures without losing their
identity, being returnable from a procedure, and never dying.

In <1991Jan7.154111.5166@d.cs.okstate.edu>, Norman Graham says that C
has first-class function pointers. He distinguishes between first-class
functions and first-class function pointers.

Finally, to complete this comedy of definitions, Ken Dickey claims in
<442@data.UUCP> that first-class objects do not have to be named, and in
<443@data.UUCP> quotes Guy Steele. According to Steele, ``full-fledged''
objects may be passed as arguments, returned as values, made part of
composite data structures, and notated as independent, unnamed entities.
He also quotes Kent Dybvig: ``Procedures are first-class data objects
similar to strings or numbers; identifiers are bound to procedures in
the same way they are bound to other objects.'' If we take this as a
definition, then ``first-class'' means only the identity properties
listed by Clinger, and does not include argument passing.

---Dan

db@cs.ed.ac.uk (Dave Berry) (01/09/91)

I don't believe it makes sense to define the attributes required
for an entity to be first-class without parameterising the definition
on a particular language.  I would say that entities of a language L
are first-class if all generic operations (i.e. not domain-specific
operations) that can be applied to other entities of L can also be
applied to the entities in question.

In functional languages, this is often (erroneously) summarised
as being able to pass entities to functions and return them from
functions.  Lennart pointed out that this definition is inadequate;
for entities to be first-class it must be possible to write them
anonymously.

IMO, the previous discussion clearly shows that for entities in C
to be first-class, it must be possible to allocate them dynamically.
This makes sense - if there were "first-class" entities in C that
couldn't be so allocated, while all/most other entities could be
so allocated, then to what class would the allocatable entities
belong?  Super executive club class with a champagne breakfast? :-)

The list of attributes given for first-class entities in Scheme
may well be an accurate definition of what "first-class" means in
Scheme.  It doesn't mean (IMO) that entities in another language
should have to satisfy those requirements to be first-class with
respect to that language.

Since most languages include procedures, functions, or similar
constructs that involve passing arguments and returning values,
it follows that this is a pretty common requirement for entities
to be firt-class.  I can't think of any language in which it is
sufficient (though there may be such languages).


>He also quotes Kent Dybvig: ``Procedures are first-class data objects
>similar to strings or numbers; identifiers are bound to procedures in
>the same way they are bound to other objects.'' If we take this as a
>definition, then ``first-class'' means only the identity properties
>listed by Clinger, and does not include argument passing.

In most languages, entities are bound to identifiers when passed as
arguments.  In some languages, argument passing can be defined as a
particular way of binding values to identifiers (Tennent's Principle
of Correspondence).  Possibly this applies to the language in
question here.

--
 Dave Berry, LFCS, Edinburgh Uni.      db%lfcs.ed.ac.uk@nsfnet-relay.ac.uk

"The Berlin Wall; the border between East and West Germany.  It's very narrow."
"*Was* very narrow.  Get your tenses right."	-- Douglas Adams, THHGTTG.

guido@cwi.nl (Guido van Rossum) (01/10/91)

Here's a different opinion.  You are all fighting over the wrong issue.

As I read them, all those "definitions" of first-class don't really
define it, but merely use a convenient term to convey a somewhat vague
but useful idea which is then explained more precisely.

The real problem with C functions (compared to Scheme or Lisp functions,
for instance) is that their "closure" only contains global variables.
This can be remedied by explicit closure parameters, and wrapper
functions, but it still is a real nuisance if your programming style
needs it a lot.  It is even worse if you are using a library provided in
object form only (no source) and there are interfaces that require you
to pass a function pointer but don't allow you to pass an extra
parameter for the closure -- you are forced to use globals which defeats
reentrancy.

On the other hand, the problem is no worse than the lack of built-in
dynamic data structures (such as variable-size arrays) in C -- everybody
knows how to roll their own, and for some this possibility is essential
because it means they aren't stuck with a built-in feature that may be
too slow or inflexible for a particular application.

--
Guido van Rossum, CWI, Amsterdam <guido@cwi.nl>
"It's probably pining for the fiords"

bevan@cs.man.ac.uk (Stephen J Bevan) (01/10/91)

In <2772@charon.cwi.nl> guido@cwi.nl (Guido van Rossum) writes :-

> As I read them, all those "definitions" of first-class don't really
> define it, but merely use a convenient term to convey a somewhat vague
> but useful idea which is then explained more precisely.

I disagree.  The definition given by Norman Graham
(<1991Jan9.061340.21668@d.cs.okstate.edu>) seems to capture exactly
what it means for an object to be first-class.  I don't see anything
vague in the idea at all.

> On the other hand, the problem is no worse than the lack of built-in
> dynamic data structures (such as variable-size arrays) in C -- everybody
> knows how to roll their own, and for some this possibility is essential
> because it means they aren't stuck with a built-in feature that may be
> too slow or inflexible for a particular application.

The efficiency argument (yet) again.  There are a number of reasons
for writing a whole application in a single language%.  However, I
don't think efficiency is one of them.  I'm sure everybody knows the
following steps :-

Write in a high level language.
Profile it.
Identify the bottlenecks.
Re-code or re-write in a lower level language.

However, most seem to equate ``high level langauge'' with C and low
level language with assembler.  Why not try ``high level langauge'' =
Scheme* and ``low level language'' = C.  It works for me, your mileage
may vary.

Stephen J. Bevan	bevan@cs.man.ac.uk

% I'm currently in the middle of writing a medium sized C program
(20,000 LOC).  I would prefer to write in some other language
(preferably Scheme/CommonLisp) , but I'm constrained by what compilers
other people have.

* Replace by your personal favourite e.g. Prolog, Smalltalk,
  CommonLisp, Self, Icon, ... etc.

gudeman@cs.arizona.edu (David Gudeman) (01/11/91)

In article  <2772@charon.cwi.nl> Guido van Rossum writes:

]The real problem with C functions (compared to Scheme or Lisp functions,
]for instance) is that their "closure" only contains global variables.

I'd say this is one of the major parts of the disagreement over the
meaning of "first-class".  Some people are trying to use the term to
compare C functions with Lisp functions, however the term is not
supposed to compare features of different languages, it is meant to
compare features of a single language.

Obviously C does not have the powerful functionals that Lisp has, but
I don't think the difference should be stated in terms of "first
class".  A better characterization would be "C does not have
functionals" or "C does not have closures", or "You cannot dynamically
create functions in C".  All of which are true (modulo a convenient
definition of "functional").
--
					David Gudeman
gudeman@cs.arizona.edu
noao!arizona!gudeman

oz@yunexus.yorku.ca (Ozan Yigit) (01/11/91)

In article <25449:Jan823:00:2991@kramden.acf.nyu.edu> Dan Bernstein writes:

>Three people---Dave Gudeman, Norman Graham, and I---seem to agree
>on a single definition of first-class.

I think I missed that definition. Would you completely spell it out
for me? Who's definition is it?

Thnx.

>All the other definitions disagree with each other on some particular.
>Must it be possible to return first-class objects from functions? Not if
>you believe Dybvig (as quoted by Dickey). Must it be possible to pass
>them as arguments? Not if you believe Clinger (as quoted by Ozan).

I don't think the ones quoted from scheme literature differ at all, and
the proof of the pudding is the language itself. On the other hand, your
confusion is understandable. The quoted authors do not attempt to supply a
pedantic enumeration of ``first-class-ness'', rather, they simply mention
that which is typically omitted from some [only some] other languages.
Neither Dybvig, nor Clinger imply what you presume they do. [take my word
for it, or you can contact them via e-mail ;-)] Incidentally, those
definitions were posted only to address your appearent disbelief in some
particulars of ``first-class functions''.

>I think the only statement we can all agree with is Lennart's claim that
>``first-class'' has several definitions.

I am not convinced that this is true.

oz
---
Yellow pages is evil. All traces of   | Internet: oz@nexus.yorku.ca
it must be vanguished from the face.  | Uucp: utzoo/utai!yunexus!oz
of the earth	   -- Eriks Rugelis   | Phone: 1+ (416) 736 5257 ..

jeff@aiai.ed.ac.uk (Jeff Dalton) (01/29/91)

In article <292@smds.UUCP> sw@smds.UUCP (Stephen E. Witham) writes:

>Bravo.  If this means that the standard of "first-class" has been raised,
>then let it be raised.  Someone (sorry, forget who) asked sarcastically
>whether Scheme introduced the concept of "first-class".  The answer is,
>in many ways, yes.  Any lesser definition is, well, second-class.

I think it's unlikely that the concept was introduced by Scheme.  It
occurred as early as 1968 in the Pop literature, and the importance
of first-class functions was already recognized.  (See one of the
early volumes of Donald Michie's _Machine Intelligence_ literature.)
I once asked Robin Popplestone (one of the inventors of Pop) where the
idea had come from, and he thought it had been "in the air" at the
time.  He remembered someone (Burstall?)  going around quoting Quine's
"to be is to be the value of a variable".

I have also heard the suggestion that the idea came from Strachey's
group at Oxford.  It certainly appears in the literature on denotational 
semantics, in particular in Stoy's book (MIT Press).  I suspect that
the work on denotational semantics led to an increased emphasis on the
lambda calculus at places such as MIT and hence to Scheme as an
"extended lambda calculus".

Once Scheme was off the ground, it became necessary to distinguish
it from other dialects of Lisp and also from the languages in the
Algol family.  Two important ideas for this purpose were referential
transparency and the first-class status of functions.

Some of the issues raised under the topic "first class" are often
raised under the topic "orthogonality" when discussing the Algol
languages.  Orthogonality is usually considered a matter of syntax,
while "first class" concerns values, but I think we can see some
of the language of orthogonality in Norman Graham's

   the language must allow the value to appear in any syntactic
   construct in which other values may occur.

Norman Graham and Dave Berry (and others) are surely right in making
"first class" be, to some extent, relative to the language.  It wouldn't
do to require first class values to be subject to assignment in a
language that didn't have assignment, for example.  

However, there is also a pragmatic component to "first class".  We
don't actually require that the value can appear in _any_ construct
in which other values can occur, nor do we require that _all_
non-domain-specific operations be applicable if we take Dave Berry's
definition:

   I would say that entities of a language L are first-class if all
   generic operations (i.e. not domain-specific operations) that can
   be applied to other entities of L can also be applied to the
   entities in question.

In particular, we do not require that first class values all have a
printed representation so that they can be input and output -- and
there are languages in which i/o is a syntactic context (eg, a print
statement in Basic) or a non-domain-specific operation (eg, write in
Scheme).  This point might also be made about Dave Berry's suggestion
that 

   for entities in C to be first-class, it must be possible to
   allocate them dynamically.

So, when we want to state what we actually do require it often makes
sense to make an explicit list, a "bill of rights".  However, the
usual aim of such is list is to give the reader the right idea rather
than to make a precise definition.  This may account for some of the
glaring omissions from some of the lists as cited in Dan Bernstein's
message:

   All the other definitions disagree with each other on some
   particular.  Must it be possible to return first-class objects
   from functions?  Not if you believe Dybvig (as quoted by Dickey).
   Must it be possible to pass them as arguments? Not if you believe
   Clinger (as quoted by Ozan). Are C's integers first-class? Only
   if you believe Lennart.

One more thing.  When we talk about "first class functions" and
whether a language has them (and similarly for objects other than
functions), it isn't _just_ a matter of relative status within a
language.  Suppose, for example, we had a language in which no
values could be passed to procedures.  All values would have the
same status in this respect, but would any of them be first-class?
I think it makes sense to say "no", even though there may be 
contexts where, strictly speaking, and given a certain meaning
of "first class", the answer would have to be "yes".

Of course, when I say "a certain meaning" there are surely some who
think "what about the (one) right meaning?"  In my opinion, we will
not be able to pin it down to One True Meaning without doing too
much violence to how the term has been used.  A technical, language-
relative definition of the sort suggested by Dave Berry will be
right for some purposes; but even then the pragmatic component may
be difficult to make precise.  In other cases, a partly language-
independent "bill of rights" may be more appropriate; and then we
may have to make exceptions for particular languages.  However, this
is not to say that all definitions are equally good, nor that we
can never answer such questions as whether functions in C are first
class.  Such questions are part of our attempt to make the concept
more precise.

(I think that was two more things.)

N.B. This is followup-to comp.lang.misc.  You may want something else.

- jd