Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Origin of the term "first-class object"

1 view
Skip to first unread message

Hung Jung Lu

unread,
Nov 17, 2003, 4:35:36 PM11/17/03
to
Hi,

Does anybody know where this term comes from?

"First-class object" means "something passable as an argument in a
function call", but I fail to see the connection with "object class"
or with "first-class airplane ticket". I just find the name a bit
strange. Also, if there are first-class objects, what would the
second-class objects or economy/tourist class objects be? :)

Just wondering,

Hung Jung

Erik Max Francis

unread,
Nov 17, 2003, 5:11:59 PM11/17/03
to
Hung Jung Lu wrote:

> Does anybody know where this term comes from?
>
> "First-class object" means "something passable as an argument in a
> function call", but I fail to see the connection with "object class"
> or with "first-class airplane ticket".

It doesn't have any connection with the former (since the term long
predates object orientation, so far as I know). It does have a
connection to the latter, in that something going first class has all
the privileges and properties owed to it as a complete and total thing.
So a "first-class object" is a complete entity unto itself, and can be
passed to functions and returned from them, as you suggest.

Think of "first-class object" as "important thing" and maybe it'll make
slightly more sense.

--
Erik Max Francis && m...@alcyone.com && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \
\__/ The only way to get rid of a temptation is to yield to it.
-- Oscar Wilde

Ben Finney

unread,
Nov 17, 2003, 4:52:46 PM11/17/03
to
On 17 Nov 2003 13:35:36 -0800, Hung Jung Lu wrote:
> "First-class object" means "something passable as an argument in a
> function call", but I fail to see the connection with "object class"
> or with "first-class airplane ticket".

The term is analogous to "first-class citizen". It implies that no
other kind of object has privilege to do more than this object, i.e. it
has the most elevated object status -- first-class.

> Also, if there are first-class objects, what would the second-class
> objects or economy/tourist class objects be? :)

Objects with fewer capabilities. E.g. in many OO-capable languages,
built-in types are not first-class objects; you (variously) can't
inherit from them, pass them as arguments, access their methods, etc.

Using this term implies, by social analogy, that the existence of
objects which are lower than first-class is undesirable and should be
rectified by elevating the status of all objects toward the ideal state:
where all are first-class.

This is why Pythonistas are proud that everything in Python is a
first-class object.

--
\ "If you get invited to your first orgy, don't just show up |
`\ nude. That's a common mistake. You have to let nudity |
_o__) 'happen.'" -- Jack Handey |
Ben Finney <http://bignose.squidly.org/>

John Roth

unread,
Nov 17, 2003, 5:11:55 PM11/17/03
to

"Hung Jung Lu" <hungj...@yahoo.com> wrote in message
news:8ef9bea6.03111...@posting.google.com...

I'm not sure who started to use it, but to me it means that
there are no restrictions on the object's use. It's the same as
any other object. I'm also not sure what being able to pass
it in a function call has to do with it; I'm used to being
able to use them in a lot of other ways.

For example, in Python both classes and functions are
objects (there are no second class citizens in Python...)
This means that I can rebind a class object into another
module at run time, and access it under its new name.
I can thow functions around with wild abandon, and even
add attributes to them for some meta-data scheme, for
example.

In Java, neither classes nor methods are first class
objects, even though you can get a "class" object
if you ask politely, it's simply a special construct
for the reflection mechanism.

In C++, neither is an object, first class or not.

John Roth


>
> Hung Jung


Mike C. Fletcher

unread,
Nov 17, 2003, 5:12:04 PM11/17/03
to Hung Jung Lu, pytho...@python.org
Hung Jung Lu wrote:

"Second class citizens" are those denied the rights afforded to "first
class citizens". In this context, first class objects are those which
can participate in the (object) environment in the same manner as any
other "normal" object. In many languages, classes are not able to be
processed in the same manner as regular objects (e.g. being passed into
functions, introspected for their type, holding properties).

HTH,
Mike

_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/


Rainer Deyke

unread,
Nov 17, 2003, 6:18:52 PM11/17/03
to
John Roth wrote:
> For example, in Python both classes and functions are
> objects (there are no second class citizens in Python...)

I would consider variables to be second-class citizens. You can change
their value, delete them, and get at the object to which they refer, but you
can't do much else with them.

> In Java, neither classes nor methods are first class
> objects, even though you can get a "class" object
> if you ask politely, it's simply a special construct
> for the reflection mechanism.
>
> In C++, neither is an object, first class or not.

While you can't create new functions and unbound methods in C++ at runtime,
you can take their address and pass that around as a first class object.
Bound methods are another matter.


--
Rainer Deyke - rai...@eldwood.com - http://eldwood.com


Erik Max Francis

unread,
Nov 17, 2003, 6:30:59 PM11/17/03
to
Rainer Deyke wrote:

> While you can't create new functions and unbound methods in C++ at
> runtime,
> you can take their address and pass that around as a first class
> object.

True, though that usually devolves into a semantic issue about whether
functions are first-class if you can only manipulate pointers to them.
I usually say C has first-class functions if you squint. C++ doesn't
have first-class bound member function pointers, as you point out, and
another obvious example in C++ is the lack of first-class classes -- a
feature in Python that is extremely powerful, since it almost makes the
"factory" pattern automatic in Python (the class object itself is just a
callable type that creates instances).

--
Erik Max Francis && m...@alcyone.com && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \

\__/ And there inside our private war / I died the night before
-- Sade

Ben Finney

unread,
Nov 17, 2003, 6:38:20 PM11/17/03
to
On Mon, 17 Nov 2003 23:18:52 GMT, Rainer Deyke wrote:
> John Roth wrote:
>> there are no second class citizens in Python...
>
> I would consider variables to be second-class citizens. You can
> change their value, delete them, and get at the object to which they
> refer, but you can't do much else with them.

AIUI, there are no "variables" in Python; or rather, the normal usage of
that term is not precise enough in Python, since the task is split.
There are names bound to objects.

Objects are all first-class.

Names are essentually a language device used to refer to an object. You
don't "change their value"; you change the object to which they are
bound.

Names aren't objects, and I don't see what you'd gain if you started
treating a name as an object; you'd merely need some additional way of
referring to *those* objects somehow. (Meta-names, anyone?)

Since names aren't objects, the question of whether they're first-class
objects doesn't arise.

--
\ "We must respect the other fellow's religion, but only in the |
`\ sense and to the extent that we respect his theory that his |
_o__) wife is beautiful and his children smart." -- Henry L. Mencken |
Ben Finney <http://bignose.squidly.org/>

John Roth

unread,
Nov 17, 2003, 7:41:28 PM11/17/03
to

"Rainer Deyke" <rai...@eldwood.com> wrote in message
news:wHcub.227649$Tr4.672235@attbi_s03...

> John Roth wrote:
> > For example, in Python both classes and functions are
> > objects (there are no second class citizens in Python...)
>
> I would consider variables to be second-class citizens. You can change
> their value, delete them, and get at the object to which they refer, but
you
> can't do much else with them.

I think I'd disagree with that. In fact, except for the optimization
within function bodies, I can't think of anything I can't do
with a name that I might want to.

John Roth


Rainer Deyke

unread,
Nov 17, 2003, 10:01:35 PM11/17/03
to
John Roth wrote:
> I think I'd disagree with that. In fact, except for the optimization
> within function bodies, I can't think of anything I can't do
> with a name that I might want to.


I can think of several things. One would be passing a name as an argument
to a function. Given the immutability of certain Python objects, it is
often necessary to write statements in the form of
"x = f(x)". This is a violation of the Once And Only Once principles, since
it mentions the same variable twice.

I'm not saying that the way Python deals with objects and variables is
wrong. Language design is a series of trade-offs, and the simplicity and
clarity of Python may very well make up for its limitations. However, that
doesn't mean that the limitations are not real.

Terry Reedy

unread,
Nov 18, 2003, 1:47:16 AM11/18/03
to

"Rainer Deyke" <rai...@eldwood.com> wrote in message
news:wHcub.227649$Tr4.672235@attbi_s03...
> I would consider variables to be second-class citizens.

In a sense, 'they' are not even citizens.

In Python, names are syntactic entities, not runtime objects (although
they sometimes get embodied in or represented as strings). They are
part of the code directing computation but are not the subject of
computation themselves (although strings representing them can be).
(But the CPython interpreter usually represents local function names
as C integers instead.) In themselves, names have neither id, type,
nor value, just a current binding to an object that does.

"Variable' is an informal term with multiple meanings even in
mathematics. In named-memory-block languages like C, a 'variable' is
a name associated with a fixed-address, mutable-content (value) block,
which before 'const', was (to my memory) every number (including
chars), array, and structure/union.

Python, being about objects rather than memory, has no direct
equivalent. Nor is there a formal definition of 'variable' for
Python. Python names are used much like C variables, but I think
people sometimes use 'variable' in a way that more refers to objects
than to names. For instance, in Python 'the value of i' is 'the value
of the ojbect currently associated with i' whereas in C it is 'the
value currently in memory block i'.

> You can change their value,

You can change the value of objects, but only the binding of names.

> delete them,

You can delete objects but only the binding of names. 'Del a' means
unbind 'a' from its currently associated object and if that was the
last remaining binding of that object, make the *object* eligible for
de-existence.

Thus far, you are using 'variable' more to describe objects than
names.

> and get at the object to which they refer,

But here you clearly mean 'variable' = 'name' unless you also mean
'variable' = collection slot or object attribute ('dotted name').

> but you can't do much else with them.

It is hard to do much with an ill-defined abstraction ;-).

Terry J. Reedy

Ben Finney

unread,
Nov 18, 2003, 2:09:55 AM11/18/03
to
On Tue, 18 Nov 2003 03:01:35 GMT, Rainer Deyke wrote:
> John Roth wrote:
>> I can't think of anything I can't do with a name that I might want
>> to.
>
> One would be passing a name as an argument
> to a function.

To accomplish what? What would you be doing with the name that you
can't do just as easily by passing the object (by reference, as always
happens in Python)?

> Given the immutability of certain Python objects, it is
> often necessary to write statements in the form of
> "x = f(x)".

I don't understand the logic here. What is it that necessitates
"x = f(x)", and why is that undesirable?

> This is a violation of the Once And Only Once principles, since it
> mentions the same variable twice.

I've never heard of that principle. Surely one of the main advantages
of naming an object is to use that name in multiple places to refer to
the object?

I can't think how you'd write any non-trivial program to work with
objects that *doesn't* "mention the same [object] twice", nor what you'd
gain by doing so.

Perhaps you're referring to a principle sometimes called the Single
Point Of Truth (SPOT), which requires that, ideally, there be one and
only one canonical place where each datum resides. This is quite
separate to the names given to objects within the program -- having a
SPOT for each datum is *enabled* by using the same name multiple times
within the program.

> Language design is a series of trade-offs, and the simplicity and
> clarity of Python may very well make up for its limitations. However,
> that doesn't mean that the limitations are not real.

I'll have to ask you to explain those limitations, I can't understand
them as you've expressed them here.

--
\ "Kissing a smoker is like licking an ashtray." -- Anonymous |
`\ |
_o__) |
Ben Finney <http://bignose.squidly.org/>

Rainer Deyke

unread,
Nov 18, 2003, 3:02:36 AM11/18/03
to
Ben Finney wrote:
> On Tue, 18 Nov 2003 03:01:35 GMT, Rainer Deyke wrote:
>> One would be passing a name as an argument
>> to a function.
>
> To accomplish what? What would you be doing with the name that you
> can't do just as easily by passing the object (by reference, as always
> happens in Python)?

Binding the name to a different object.

>> Given the immutability of certain Python objects, it is
>> often necessary to write statements in the form of
>> "x = f(x)".
>
> I don't understand the logic here. What is it that necessitates
> "x = f(x)",

For example, any "mutating" operation on x, where x is an immutable object.

Trivial and useless example:

def increment(x):
return x + 1

i = increment(i)

> and why is that undesirable?

Suppose the 'x' in 'x = f(x)' is not a simple variable, but an element in a
list

l[x * 2 + f(y)] = f(l[x * 2 + f(y)])

This statement contains an obvious redundancy that will make code
maintenance difficult. Python allows me to factor out some of the
redundancy:

index = x * 2 + f(y)
l[index] = f(l[index])

However, Python gives me no way to factor out the remaining redundancy.

John J. Lee

unread,
Nov 18, 2003, 6:56:37 AM11/18/03
to
Erik Max Francis <m...@alcyone.com> writes:

> Hung Jung Lu wrote:
>
> > Does anybody know where this term comes from?
> >
> > "First-class object" means "something passable as an argument in a
> > function call", but I fail to see the connection with "object class"
> > or with "first-class airplane ticket".
>
> It doesn't have any connection with the former (since the term long
> predates object orientation, so far as I know). It does have a
> connection to the latter, in that something going first class has all
> the privileges and properties owed to it as a complete and total thing.

[...]

Ben is closer to the mark in terms of etymology, I think -- though
maybe "first-class citizen" in turn derives from "first-class ticket"?


John

John Roth

unread,
Nov 18, 2003, 7:41:57 AM11/18/03
to

"Ben Finney" <bignose-h...@and-benfinney-does-too.id.au> wrote in
message news:slrnbrjijj.105.b...@rose.localdomain.fake...

>
> > This is a violation of the Once And Only Once principles, since it
> > mentions the same variable twice.
>
> I've never heard of that principle.

Different authors give it different names. Dave Thomas and
Mike Hunt (the Pragmatic Programmers) call it "DRY":
"Don't repeat yourself." Once and only once comes, I believe,
from XP. There are other names.

The essential concept is that there should only be one
location for something in a system. Complaining about
x = f(x) is, IMO, being excessively anal about it.

John Roth


Aahz

unread,
Nov 18, 2003, 9:59:07 AM11/18/03
to
In article <wmkub.177225$9E1.927898@attbi_s52>,

Rainer Deyke <rai...@eldwood.com> wrote:
>
>Suppose the 'x' in 'x = f(x)' is not a simple variable, but an element in a
>list
>
>l[x * 2 + f(y)] = f(l[x * 2 + f(y)])
>
>This statement contains an obvious redundancy that will make code
>maintenance difficult. Python allows me to factor out some of the
>redundancy:
>
>index = x * 2 + f(y)
>l[index] = f(l[index])
>
>However, Python gives me no way to factor out the remaining redundancy.

Sure it does: change the immutable to a mutable.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

Weinberg's Second Law: If builders built buildings the way programmers wrote
programs, then the first woodpecker that came along would destroy civilization.

Mel Wilson

unread,
Nov 18, 2003, 10:07:10 AM11/18/03
to
In article <slrnbrjijj.105.b...@rose.localdomain.fake>,

Ben Finney <bignose-h...@and-benfinney-does-too.id.au> wrote:
>On Tue, 18 Nov 2003 03:01:35 GMT, Rainer Deyke wrote:
>> John Roth wrote:
>>> I can't think of anything I can't do with a name that I might want
>>> to.
>>
>> One would be passing a name as an argument
>> to a function.
>
>To accomplish what? What would you be doing with the name that you
>can't do just as easily by passing the object (by reference, as always
>happens in Python)?

That's rather beside the point, isn't it? People
continually come to c.l.p asking how to get the names of
function parameters. Some are trying to write diagnostic
routines. Some people want to know how to make data names
out of user input strings; we tell them to for heaven's sake
use a dictionary.

It's not unreasonable to give names as an example of
second-class objects in Python.

And a good thing, as you and I think. Names are
first-class in natural human languages, and look what
happens:

"...The name of the song is called 'Haddocks'
Eyes'."

"Oh, that's the name of the song, is it?" Alice
said, trying to feel interested.

"No, you don't understand," the Knight said,
looking a little vexed. "That's what the name is
_called_. The name really is 'The Aged Aged Man'."

"Then I ought to have said 'That's what the song is
called'?" Alice corrected herself.

"No, you oughtn't! That's quite another thing!
The song is called 'Ways and Means': but that's only
what it's called, you know."

"Well, what is the song then?" said Alice, who was
by this time completely bewildered.

"I was coming to that," the Knight said. "The song
really is 'A-sitting on a Gate', and the tune's my
own invention."

_Through the Looking Glass_, of course
Lewis Carroll

Regards. Mel.

Peter Hansen

unread,
Nov 18, 2003, 12:59:01 PM11/18/03
to
Mel Wilson wrote:
>
> And a good thing, as you and I think. Names are
> first-class in natural human languages, and look what
> happens:
>
> "...The name of the song is called 'Haddocks'
> Eyes'."
>
> "Oh, that's the name of the song, is it?" Alice
> said, trying to feel interested.
>
> "No, you don't understand," the Knight said,
> looking a little vexed. "That's what the name is
> _called_. The name really is 'The Aged Aged Man'."
>
> "Then I ought to have said 'That's what the song is
> called'?" Alice corrected herself.
>
> "No, you oughtn't! That's quite another thing!
> The song is called 'Ways and Means': but that's only
> what it's called, you know."
>
> "Well, what is the song then?" said Alice, who was
> by this time completely bewildered.
>
> "I was coming to that," the Knight said. "The song
> really is 'A-sitting on a Gate', and the tune's my
> own invention."
>
> _Through the Looking Glass_, of course
> Lewis Carroll

Wow! That shows just how precise one can sometimes need to be,
especially with things like "names" in Python (which we sometimes
call variables, but which actually are just *bindings* ;-).

-Peter

Rainer Deyke

unread,
Nov 18, 2003, 2:10:10 PM11/18/03
to
Aahz wrote:
>> l[x * 2 + f(y)] = f(l[x * 2 + f(y)])
>>
>> This statement contains an obvious redundancy that will make code
>> maintenance difficult. Python allows me to factor out some of the
>> redundancy:
>>
>> index = x * 2 + f(y)
>> l[index] = f(l[index])
>>
>> However, Python gives me no way to factor out the remaining
>> redundancy.
>
> Sure it does: change the immutable to a mutable.

Not good enough. I'd rather write "l[x] = f(l[x])" with all of its
redundancy than wrap every conceivable immutable object in a mutable
wrapper. Besides, I don't *want* 'f' to change an object (which may also be
referenced elsewhere); I want it to change a binding.

And, really, "l[x] = f(l[x])" isn't that big of a deal. It's a bit of
redundancy that I'd rather not have, but it's not bad enough that I feel the
need to do anything about it.

John Roth

unread,
Nov 18, 2003, 3:55:44 PM11/18/03
to

"Rainer Deyke" <rai...@eldwood.com> wrote in message
news:jYfub.229477$Tr4.681061@attbi_s03...

> John Roth wrote:
> > I think I'd disagree with that. In fact, except for the optimization
> > within function bodies, I can't think of anything I can't do
> > with a name that I might want to.
>
>
> I can think of several things. One would be passing a name as an argument
> to a function.

Given your example below, I *think* you're asking to be able
to pass a *something* that allows you to bind an object to an
identifier in another object. I don't think it would be particularly
difficult to create an object that could do this, but I'd really
have to be convinced as to why there isn't any simpler way to
accomplish the (unstated) end result, especially since the potential
for very hard to diagnose coupling and side effects is horrendous.

> Given the immutability of certain Python objects, it is
> often necessary to write statements in the form of
> "x = f(x)". This is a violation of the Once And Only Once principles,
since
> it mentions the same variable twice.

That's a very weak reason.

John Roth

Aahz

unread,
Nov 24, 2003, 12:33:40 PM11/24/03
to
In article <m8uub.235682$HS4.2034763@attbi_s01>,
Rainer Deyke <rai...@eldwood.com> wrote:
>Aahz wrote:
>>Rainer:

>>>
>>> l[x * 2 + f(y)] = f(l[x * 2 + f(y)])
>>>
>>> This statement contains an obvious redundancy that will make code
>>> maintenance difficult. Python allows me to factor out some of the
>>> redundancy:
>>>
>>> index = x * 2 + f(y)
>>> l[index] = f(l[index])
>>>
>>> However, Python gives me no way to factor out the remaining
>>> redundancy.
>>
>> Sure it does: change the immutable to a mutable.
>
>Not good enough.

Why not? Note that you're playing what is IMO an unfair game where you
keep changing the goalposts.

>I'd rather write "l[x] = f(l[x])" with all of its redundancy than wrap
>every conceivable immutable object in a mutable wrapper. Besides, I
>don't *want* 'f' to change an object (which may also be referenced
>elsewhere); I want it to change a binding.

Well, you're going to have to pay for what you want in some fashion;
Python's going to keep its default semantics, so you're going to need
*some* kind of wrapper.

>And, really, "l[x] = f(l[x])" isn't that big of a deal. It's a bit of
>redundancy that I'd rather not have, but it's not bad enough that I
>feel the need to do anything about it.

<shrug> It's not a redundancy unless you're using a particular skewed
way of looking at things. If you're going to skew, you might as well
keep skewing until you're using a Pythonic mechanism.

Jp Calderone

unread,
Nov 24, 2003, 1:58:10 PM11/24/03
to pytho...@python.org
On Mon, Nov 24, 2003 at 12:33:40PM -0500, Aahz wrote:
> In article <m8uub.235682$HS4.2034763@attbi_s01>,
> Rainer Deyke <rai...@eldwood.com> wrote:
> >Aahz wrote:
> >>Rainer:
> >>>
> >>> l[x * 2 + f(y)] = f(l[x * 2 + f(y)])
> >>>
> >>> This statement contains an obvious redundancy that will make code
> >>> maintenance difficult. Python allows me to factor out some of the
> >>> redundancy:
> >>>
> >>> index = x * 2 + f(y)
> >>> l[index] = f(l[index])
> >>>
> >>> However, Python gives me no way to factor out the remaining
> >>> redundancy.
> >>
> >> Sure it does: change the immutable to a mutable.
> >
> >Not good enough.
>
> Why not? Note that you're playing what is IMO an unfair game where you
> keep changing the goalposts.
>
> >I'd rather write "l[x] = f(l[x])" with all of its redundancy than wrap
> >every conceivable immutable object in a mutable wrapper. Besides, I
> >don't *want* 'f' to change an object (which may also be referenced
> >elsewhere); I want it to change a binding.
>
> Well, you're going to have to pay for what you want in some fashion;
> Python's going to keep its default semantics, so you're going to need
> *some* kind of wrapper.

Up for a new operator?

l[index] ()= f

<1.5-wink>, Jp

Aahz

unread,
Nov 24, 2003, 3:38:11 PM11/24/03
to
In article <mailman.1031.106970...@python.org>,

"Boot to the head. <thump>"

Greg Ewing (using news.cis.dfn.de)

unread,
Nov 24, 2003, 9:07:22 PM11/24/03
to
Jp Calderone wrote:

> Up for a new operator?
>
> l[index] ()= f

I like it! :-)

I suppose you should be able to put extra args in, too, e.g.

l[index] (foo, 42)= f

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Bengt Richter

unread,
Nov 25, 2003, 3:28:09 PM11/25/03
to
On Tue, 25 Nov 2003 15:07:22 +1300, "Greg Ewing (using news.cis.dfn.de)" <g2h5d...@sneakemail.com> wrote:

>Jp Calderone wrote:
>
>> Up for a new operator?
>>
>> l[index] ()= f
>
>I like it! :-)
>

Me too ;-)
But I wonder if =()= wouldn't read more clearly, e.g.,

l[index] =()= f

and see below.

>I suppose you should be able to put extra args in, too, e.g.
>
> l[index] (foo, 42)= f
>

I presume that would imply that f had all optional args after the first.
What if you wanted to pass the update target in another position? E.g.,

l[index] =(foo, ??, 42)= f

where ?? is some kind of indicator for where to plug in the arg. I guess you
could use packing/unpacking if you had a tuple left side and several ??'s to match, e.g.,

a, l[index] =(foo, ??, 42, ??)= f

meaning

a, l[index] = f(foo, a, 42, l[index])

or course the targets could be simple as well

a, b =(foo, ??, ??, 42)= f

meaning

a, b = f(foo, a, b, 42)

Hm, I wonder about * for pack/unpack into arg tuple in this context

a, b =(foo, *??, 42)= f

maybe meaning

a, b = f(foo, (a,b), 42)

or did I get that backwards?

Sorry, can't help it ;-)

Regards,
Bengt Richter

0 new messages