"Ternary" just means "takes three arguments," the ternary operator in C is called that because it's the only ternary operator in C; all the others take fewer than three arguments.
This issue also has to do with what you mean by "pointer." We use the word to mean pointers in the sense of building pointer-linked data structures. (Scheme clearly has those.) Some people use "pointers" to mean addresses that are bit patterns you can manipulate directly--the way you can in C, where you can "cast" (coerce) a pointer to an integer and operate on the bits. Some people use "pointer" synonymously with "address", and call what Scheme has object references.
An unsafe cast is one that the compiler doesn't
really understand. A safe cast is one that makes sense to the
compiler, such as converting an integer to a floating point number.
With unsafe casts, you're essentially telling the compiler "trust
me", and bypassing the type systems. This kind of unsafe cast
is what happens when
you cast a structure pointer to a void*
or char*
and later cast it back to a structure pointer--you're promising
the compiler that the pointer will actually point to a structure
of the declared type, and it's up to you to make sure that's true.
Note that here "variable" just means that it varies, and arity means that what's varying is the number of argument variables. "Arity" comes from words like "nullary," "unary," "binary," and "ternary"---these mean zero-argument, one-argument, two-argument, and three-argument, respectively. (Sometimes people say things like "1-ary" for unary (one argument), "2-ary" for binary, and "n-ary" for "variable arity.")
Consider an improper list (a b . c)
.
Here the first element of the list is a, the cadr
of the
list is b
, and the rest of the list beyond that
(the cddr
) is just c
. If we write the argument
declarations of a procedure in this way, e.g.,
(lambda (a b . c) ...)
, we think of the formal parameter
a
as "standing for" the first actual argument value, the
formal parameter b
as standing for the second actual
argument value, and the formal parameter c
as standing
for the rest of the actual argument values.
Here the analogy may not be very intuitive;
it's as though you used a name like x
to refer to different
"people" at different times, but those people were all alike,
and uninteresting except for what you call them and what they
point at with their index fingers. In this analogy, set!
is
like telling one of these very boring people "point at that
for now."
For example, we can
call read
to read the list (foo 20 (baz))
, and
then just use that list as a list, rather than
interpreting it as a piece of a program.
Unsurprisingly, a bottom-up parser would do the opposite--it would recognize the smaller constituents first, and then recognize the larger phrases that contain them.
In the technical terminology of programming language processors, the reader is a predictive parser for an LL(0) grammar. It can parse s-expressions top-down in a single pass through the sequence of tokens, without looking ahead past the current token, because it only needs to see the current token to know what action to take. (E.g., if it sees a left parenthesis, it immediately "knows" that it is parsing a nested list.)
It's often said that Lisp and Scheme have such a simple syntax that they "don't need a parser," but this is just false. Lisp and Scheme actually have two parsers, because their syntax has a two levels. The "surface" syntax is parenthesized prefix expressions, recognized by the reader and translated into s-expression data structures. There is a "deeper" syntax that is recognized by the interpreter or compiler, which analyzes s-expressions to see what kinds of Scheme program expressions they represent, in the process of evaluating or compiling them. As we'll see when we get to macros, Scheme syntax is even more sophisticated than this, despite its simplicity. Technically, Scheme has a transformational grammar that is not "context-free," but is easy to parse. (If you don't know what that means, don't worry about it. Scheme is easy to understand without knowing the fancy technical terms.)
The compiler can generally avoid the overhead of closures where it's not actually useful--if you write C-like or Pascal-like programs, the compiler can generate very similar code. And if you really use closures in their full generality, it's not particularly slow--a few extra instructions per procedure call. Creating closures can be surprisingly fast, because Scheme systems typically have allocators several times faster than most C allocators. [should discuss efficiency issues in more detail in a later chapter...]
This is
something of an oversimplification. The quoted expression is generally
converted to a list at read
time, and the value of the quote
expression may be the very same data structure, or it may be a copy
made later during compilation or interpretation. At any rate, you
should only count on the structure of a quoted data structure,
not its identity. A compiler or interpreter is allowed to return the
same list for different quote
d data structures with the same
structure.
Superclasses
can be used to specify a class as a set of differences
from an existing class, rather than describing everything
about the class from scratch. Here we're saying that the
<point>
class is just like any other class of objects,
and does the normal things classes do, but nothing special
except what we specify explictily in the class definition.
The
object <class>
is actually the class object of class
objects---classes are instances of the class <class>
.
This will be explained in detail later.
Evaluating
the quasiquote expression `(,<object>)
will create a
list containing the actual class object that is the value of
the variable <object>
.
This is important to understand in being able to read clever macros: a quoted expression isn't just a literal if it has unquoted expressions inside it, because we're generating a literal with the macro. (It's not a literal in the macro, but the resulting s-expression will be a literal when the interpreter or compiler sees it, after the macro has done its transformation--the quoted expression is really a template for a literal, which we can specialize to produce the literal we want.)