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

Common-Lisp "Primitives"

77 views
Skip to first unread message

Pascal Bourguignon

unread,
Dec 28, 2003, 3:14:30 PM12/28/03
to

The question has already been asked, and while it has not a unique
answer, what would you think of this list of Common-Lisp primitives?
(in low-case the special operators and forms that are considered
primitive, but some would be implemented in the non-primitive EVAL).

Did I miss any? Any of these functions could be trivially implemented
in function of the others?

Would TYPE-OF need to be primitive?
What about the type hierarchy in general?


Of course, this does not take into account bootstrapping problems (you
may need a reader to load an image with the definitions of the rest of
the Common-Lisp package).


03-evaluation-and-compilation

COMPILER-MACRO-FUNCTION MACRO-FUNCTION

eval-when load-time-value quote symbol-macrolet locally the flet
labels macrolet function let let* progv setq block catch go
return-from tagbody throw unwind-protect if multiple-value-call
multiple-value-prog1 progn


04-types-and-classes

None


05-data-and-control-flow

NIL T APPLY FUNCTION-LAMBDA-EXPRESSION EQ EQL VALUES

flet labels macrolet function let let* progv setq block catch go
return-from tagbody throw unwind-protect if multiple-value-call
multiple-value-prog1 progn


06-iteration

None


07-objects

None

10-symbols

SYMBOLP MAKE-SYMBOL SYMBOL-FUNCTION SYMBOL-NAME SYMBOL-PACKAGE
SYMBOL-PLIST SYMBOL-VALUE MAKUNBOUND BOUNDP


11-packages

None


12-numbers

Most of them.

(fixnum could be considered primitive and the rest built on them,
which is orthogonal to most of the function defined in the Number
chapter).


13-characters

CHARACTERP CHAR-CODE CHAR-INT CODE-CHAR


14-conses

ATOM CONSP CONS RPLACA RPLACD CAR CDR


15-arrays

MAKE-ARRAY ARRAYP ADJUST-ARRAY ADJUSTABLE-ARRAY-P ARRAY-DIMENSIONS
ARRAY-ELEMENT-TYPE ARRAY-HAS-FILL-POINTER-P ARRAY-DISPLACEMENT
ARRAY-IN-BOUNDS-P FILL-POINTER ROW-MAJOR-AREF ARRAY-ROW-MAJOR-INDEX


16-strings

None


17-sequences

None


18-hash-tables

MAKE-HASH-TABLE HASH-TABLE-P HASH-TABLE-COUNT
HASH-TABLE-REHASH-SIZE HASH-TABLE-REHASH-THRESHOLD HASH-TABLE-SIZE
HASH-TABLE-TEST GETHASH REMHASH MAPHASH SXHASH


19-filenames

None


20-files

DIRECTORY PROBE-FILE ENSURE-DIRECTORIES-EXIST TRUENAME FILE-AUTHOR
FILE-WRITE-DATE RENAME-FILE DELETE-FILE


21-streams

Not determined yet. Cf. underlying I/O?


22-printer

None


23-reader

None


24-system-construction

None


25-environment

SLEEP GET-UNIVERSAL-TIME ROOM LISP-IMPLEMENTATION-TYPE
LISP-IMPLEMENTATION-VERSION SHORT-SITE-NAME LONG-SITE-NAME
MACHINE-INSTANCE MACHINE-TYPE MACHINE-VERSION SOFTWARE-TYPE
SOFTWARE-VERSION USER-HOMEDIR-PATHNAME

--
__Pascal_Bourguignon__ . * * . * .* .
http://www.informatimago.com/ . * . .*
There is no worse tyranny than to force * . . /\ . *
a man to pay for what he does not . . / .\ . * .
want merely because you think it .*. / * \ . .
would be good for him. -- Robert Heinlein . /* o \ .
http://www.theadvocates.org/ * '''||''' .
SCO Spam-magnet: postm...@sco.com ******************

sajiimori

unread,
Dec 28, 2003, 3:59:29 PM12/28/03
to
Note: I've only been using CL for a few weeks.

Could LET* be implemented as a series of nested LETs?

Should SET or SETQ be a primitive, considering that SETQ stands for (SET
(QUOTE...? Can SET be implemented in terms of SETQ by explicitly evaluating
the first argument?

Should OS calls such as DELETE-FILE really be considered primitives, in the
same sense as CDR, CONS, and ATOM, or should they be thought of as analagous
to the corresponding ANSI C library functions (i.e. mere utilities rather
than actual language elements)?


Kent M Pitman

unread,
Dec 28, 2003, 3:59:45 PM12/28/03
to
Pascal Bourguignon <sp...@thalassa.informatimago.com> writes:

> The question has already been asked, and while it has not a unique
> answer, what would you think of this list of Common-Lisp primitives?
> (in low-case the special operators and forms that are considered
> primitive, but some would be implemented in the non-primitive EVAL).

What is primitive and what is not is largely an efficiency issue. If
you're in control of the implementatin, a great many you mentioned
don't have to be primitive. If you're not in control of the
implementation, the question is what your use is. The answer for a
code-walker is different than for a teaching subset. It's ridiculous
to assume that they form an exhaustive set so powerful that you will
never have to ask the implementor for further "support", and so if all
you want to know is "sufficient to implement things on top" then the
question is what you're going to implement. Surely there are things
you'd want from underneath to help you rather than to use these to
implement even the set of things you _could_ implement with these.

SYMBOL-PACKAGE, for example, is easily implemented with GETHASH,
modulo issues of efficiency. But if efficiency is paramount, then
many of these while they may serve many applications well may still
not get you every ounce of power that revealing some other item would.

APPLY may be better implemented with FUNCALL than FUNCALL with APPLY
because FUNCALL does not cons and forcing everything through APPLY
probably forces consing in some cases you don't want.

TYPE-OF is indeed impossible to implement portably, and yet has no real
purpose other than debugging, so makes a very odd "primitive".

CHAR-INT, CHAR-CODE, and CODE-CHAR make a motley set of primitives.
Better on a per-implementation basis to say there are primitives but
you don't know what they are. The real "primitives" were not yet fit
for standardization because of widespread experimentation at press
time.

Since (ATOM x) = (NOT (CONSP x)), it makes no sense to have both ATOM
and CONSP be primitive.

RPLACA and RPLACD are not primitive if you have SETF. If you don't have
SETF, there are a number of operations you can't get the setter for.

CL, as a community consensus, for this reason, doesn't distinguish
between primitive and non-primitive. IMO, it's a waste of time to do
out-of-context. It may have a lot of importance within a context, but
since you have specified none, I think it has very little importance.
Of course, I count as "context" the idea of "important to Pascal
Bourguignon". That's a valid context in which to list the notion of
important or primitive. But it doesn't require others to agree....

Frode Vatvedt Fjeld

unread,
Dec 28, 2003, 4:22:03 PM12/28/03
to
"sajiimori" <saji...@hotmail.com> writes:

> Could LET* be implemented as a series of nested LETs?

Almost. The only issue is that of declarations. I.e. you must make
sure that

(let* ((x 1) (y 2))
(declare (type integer y) (special x))
...)

becomes something like

(let ((x 1))
(declare (special x))
(let ((y 2))
(declare (type integer y))
...))

> Should SET or SETQ be a primitive, considering that SETQ stands for
> (SET (QUOTE...? Can SET be implemented in terms of SETQ by
> explicitly evaluating the first argument?

You can't implement set with setq. But you can mostly implement setq
in terms of set, like this:

(defmacro setq (place value)
(check-type place symbol "a variable name")
`(set ',place ,value))

But, only "mostly", because it actually needs to be something like
this:

(defmacro setq (place value)
(check-type place symbol "a variable name")
(cond
((symbol-macro-p place)
`(setf ,place ,value))
((special-variable-p place)
`(set ',place ,value))
((lexical-variable-p place)
`(set-lexical ,place ,value))
(t (error "Huh?"))))

> Should OS calls such as DELETE-FILE really be considered primitives,
> in the same sense as CDR, CONS, and ATOM, or should they be thought
> of as analagous to the corresponding ANSI C library functions
> (i.e. mere utilities rather than actual language elements)?

Before asking this question, you should ask yourself if the answer
would have any consequence one way or the other. I don't think it
would. So why ask it?

--
Frode Vatvedt Fjeld

sajiimori

unread,
Dec 28, 2003, 4:27:03 PM12/28/03
to
Thanks for the interesting answers.

> Before asking this question, you should ask yourself if the answer
> would have any consequence one way or the other. I don't think it
> would. So why ask it?

Meh...just a philisophical thing I guess. ;-) All I'm really asking is how
other people think about such things, not so much what the "right" answer
is.


Pascal Bourguignon

unread,
Dec 28, 2003, 5:11:54 PM12/28/03
to

"sajiimori" <saji...@hotmail.com> writes:

> Note: I've only been using CL for a few weeks.
>
> Could LET* be implemented as a series of nested LETs?
>
> Should SET or SETQ be a primitive, considering that SETQ stands for (SET
> (QUOTE...? Can SET be implemented in terms of SETQ by explicitly evaluating
> the first argument?

These are special operators. If I read correctly the CLHS glossary:

special form n. a list, other than a macro form, which is a form
with special syntax or special evaluation rules or both, possibly
manipulating the evaluation environment or control flow or
both. The first element of a special form is a special operator.

special operator n. one of a fixed set of symbols, enumerated in
Figure 3-2, that may appear in the car of a form in order to
identify the form as a special form.

that would mean that special forms can't be macro forms therefore
special operators can't be macros.

Note also that the definition for compiler macro:

compiler macro n. an auxiliary macro definition for a globally
defined function or macro which might or might not be called by
any given conforming implementation and which must preserve the
semantics of the globally defined function or macro but which
might perform some additional optimizations. (Unlike a macro, a
compiler macro does not extend the syntax of Common Lisp; rather,
it provides an alternate implementation strategy for some existing
syntax or functionality.)

seems to indicate that cannot even have a compiler macro for special forms.


> Should OS calls such as DELETE-FILE really be considered primitives, in the
> same sense as CDR, CONS, and ATOM, or should they be thought of as analagous
> to the corresponding ANSI C library functions (i.e. mere utilities rather
> than actual language elements)?


Like for LET* vs. LET, there could be internal more primitive
functions on which the special operators and stream functions could be
implemented. But at this stage, I'm not thinking about what low level
"primitive" function is needed to implement Common-Lisp, but rather
what functions in Common-Lisp can be implemented using only a kernel
set of Common-Lisp. These non-primitive functions and the macros of
Common-Lisp could then be implemented in 100% pure Common-Lisp and be
considered as the Common-Lisp library.

Pascal Costanza

unread,
Dec 28, 2003, 5:21:41 PM12/28/03
to

sajiimori wrote:

> Note: I've only been using CL for a few weeks.

This statement...

> Should OS calls such as DELETE-FILE really be considered primitives, in the
> same sense as CDR, CONS, and ATOM, or should they be thought of as analagous
> to the corresponding ANSI C library functions (i.e. mere utilities rather
> than actual language elements)?

...and this question are related AFAICT. One of the cool things about
Common Lisp is that you can make your own libraries appear to be part of
the language, in the sense that there is no (syntactical) difference
between language and library.

Here is a possible take on this: Think about what you would consider a
reasonable boundary between a library function and a primitive function.
For example, CONS already interacts in non-trivial ways with memory
management, which is usually an important library of the operating
system. So is it a primitive function or a library function? (Hint: The
description I have given includes the word "library" but not "primitive". ;)

In a strict sense, it is always the case that one man's primitive is
another man's library. I think it is in this sense that Frode Vatvedt
Fjeld has already given the best answer.


Pascal

--
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."

Pascal Bourguignon

unread,
Dec 28, 2003, 5:56:41 PM12/28/03
to
Kent M Pitman <pit...@nhplace.com> writes:

> Pascal Bourguignon <sp...@thalassa.informatimago.com> writes:
>
> > The question has already been asked, and while it has not a unique
> > answer, what would you think of this list of Common-Lisp primitives?
> > (in low-case the special operators and forms that are considered
> > primitive, but some would be implemented in the non-primitive EVAL).
>
> What is primitive and what is not is largely an efficiency issue. If
> you're in control of the implementatin, a great many you mentioned
> don't have to be primitive. If you're not in control of the
> implementation, the question is what your use is. The answer for a
> code-walker is different than for a teaching subset. It's ridiculous
> to assume that they form an exhaustive set so powerful that you will
> never have to ask the implementor for further "support", and so if all
> you want to know is "sufficient to implement things on top" then the
> question is what you're going to implement. Surely there are things
> you'd want from underneath to help you rather than to use these to
> implement even the set of things you _could_ implement with these.
>
> SYMBOL-PACKAGE, for example, is easily implemented with GETHASH,
> modulo issues of efficiency. But if efficiency is paramount, then
> many of these while they may serve many applications well may still
> not get you every ounce of power that revealing some other item would.

> CL, as a community consensus, for this reason, doesn't distinguish
> between primitive and non-primitive. IMO, it's a waste of time to do
> out-of-context. It may have a lot of importance within a context, but
> since you have specified none, I think it has very little importance.
> Of course, I count as "context" the idea of "important to Pascal
> Bourguignon". That's a valid context in which to list the notion of
> important or primitive. But it doesn't require others to agree....

Let's say it's in the context of developping a Common-Lisp
implementation in Common-Lisp.


> APPLY may be better implemented with FUNCALL than FUNCALL with APPLY
> because FUNCALL does not cons and forcing everything through APPLY
> probably forces consing in some cases you don't want.

I chose APPLY over FUNCALL for it accepts a list of parameters while
FUNCALL does not. I'm expecting to be needing this to implement the
lambda lists.

> TYPE-OF is indeed impossible to implement portably, and yet has no real
> purpose other than debugging, so makes a very odd "primitive".

More important than portability, auto-documentation! I just had the
problem with an implementation of scheme lacking a TYPE-OF: it's
almost impossible to know how to handle some return values when you
don't have any online documentation.


> CHAR-INT, CHAR-CODE, and CODE-CHAR make a motley set of primitives.
> Better on a per-implementation basis to say there are primitives but
> you don't know what they are. The real "primitives" were not yet fit
> for standardization because of widespread experimentation at press
> time.

We lack functions to set the (implementation dependant) attributes of
a character. But otherwise, I see CODE-CHAR as a MAKE-CHAR function,
and CHAR-INT as a query for the implementation dependant attributes.

Eventually I guess the ultimate source of characters is the I/O. I've
not thought about I/O yet, but if the primitive I/O is reading a byte
(as 0..255 number), then characters must all be built with
CODE-CHAR. Other implementation dependant character attributes come
from input too.


> Since (ATOM x) = (NOT (CONSP x)), it makes no sense to have both ATOM
> and CONSP be primitive.

Indeed. I'll remove ATOM.


> RPLACA and RPLACD are not primitive if you have SETF. If you don't have
> SETF, there are a number of operations you can't get the setter for.

What operations do you have in mind?

Let's assume that for accessors I've marked "primitive" a
corresponding defsetf will be defined (I put RPLACA and RPLACD in that
category, but you're right, it's not orthogonal and I should perhaps
only have the defsetf for car and cdr and implement RPLACA and RPLACD
in function of them; ).
Otherwise I think that I'll be able to implement a defsetf for all
non-"primitive", since both SETF and the other non-"primitives" will
be implemented "at the same time".
So I'd take none of RPLACA, RPLACD or SETF as "primitive".

Frode Vatvedt Fjeld

unread,
Dec 28, 2003, 6:00:57 PM12/28/03
to
Pascal Bourguignon <sp...@thalassa.informatimago.com> writes:

> [..] that would mean that special forms can't be macro forms


> therefore special operators can't be macros.

This is wrong, as stated explicitly in CLHS 3.1.2.1.2.2 Macro Forms.

> [..] seems to indicate that cannot even have a compiler macro for
> special forms.

I don't think users are allowed to add compiler-macros for /any/
operator defined in CL.

--
Frode Vatvedt Fjeld

Jakub Travnik

unread,
Dec 28, 2003, 6:22:13 PM12/28/03
to
On Sun, 28 Dec 2003 21:14:30 +0100, Pascal Bourguignon wrote:

>
> The question has already been asked, and while it has not a unique
> answer, what would you think of this list of Common-Lisp primitives?
> (in low-case the special operators and forms that are considered
> primitive, but some would be implemented in the non-primitive EVAL).

Interesting text about CL primitives is at:

http://home.pipeline.com/~hbaker1/MetaCircular.html


Jakub Travnik
jabber://jt...@jabber.com

Frank A. Adrian

unread,
Dec 28, 2003, 8:13:45 PM12/28/03
to
On Sun, 28 Dec 2003 21:14:30 +0100, Pascal Bourguignon wrote:

> The question has already been asked, and while it has not a unique
> answer, what would you think of this list of Common-Lisp primitives?

I think it's much too high level. I'd go with the following:

(peek addr ret-addr)
(poke addr val)
(call addr)

Am I being facetious? Maybe a bit.

I guess my point is that your set of primitives would probably work as
well as anyone elses. It's almost never a question of "Is it enough?",
but one of "Is it convenient and does it perform well?"

faa

Pascal Bourguignon

unread,
Dec 29, 2003, 5:22:15 PM12/29/03
to
Frode Vatvedt Fjeld <fro...@cs.uit.no> writes:

> Pascal Bourguignon <sp...@thalassa.informatimago.com> writes:
>
> > [..] that would mean that special forms can't be macro forms
> > therefore special operators can't be macros.
>
> This is wrong, as stated explicitly in CLHS 3.1.2.1.2.2 Macro Forms.

Thank you. I don't have uploaded the whole CLHS in my mind yet.
I've read somewhere the upload bandwidth in wetware is about 2 bit/sec.


> > [..] seems to indicate that cannot even have a compiler macro for
> > special forms.
>
> I don't think users are allowed to add compiler-macros for /any/
> operator defined in CL.


--

Pascal Bourguignon

unread,
Dec 29, 2003, 5:31:36 PM12/29/03
to
Jakub Travnik <j.tr...@sh.cvut.cz.nospam> writes:

Indeed, most interesting. Thank you.

Christophe Rhodes

unread,
Jan 3, 2004, 5:48:03 PM1/3/04
to
Pascal Bourguignon <sp...@thalassa.informatimago.com> writes:

> The question has already been asked, and while it has not a unique
> answer, what would you think of this list of Common-Lisp primitives?

I think that a list without a corresponding implementation is
completely worthless.

Christophe
--
http://www-jcsu.jesus.cam.ac.uk/~csr21/ +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%") (pprint #36rJesusCollegeCambridge)

0 new messages