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 ******************
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)?
> 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....
> 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
> 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.
> 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.
> 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 <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".
> [..] 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
>
> 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
> 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 <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.
--
Indeed, most interesting. Thank you.
> 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)