Common LISP has turned any Function a Symbol holds, into An Additional Field.

I had started to write about this subject some time ago.

This was a posting of mine, in which I pondered the more-general question, of how different LISP variants may recognize, that they have encountered a List or an Atom.

In this posting, I went into the specific question more, of how to use Common LISP, and manipulate the distinction between Symbols that store Functions, and Symbols that store Lists. Obviously, Common LISP requests, that we use the built-in function (symbol-function) to refer specifically to the Function stored within.

And in this posting, I carried out a very basic experiment, to see whether a data-type is stored on the plist, in Common LISP. The answer was No.

I should not even refer to my experiments as such, because they are too rudimentary to qualify. Instead, these are simple efforts to educate myself – and anybody else who might be curious enough to read my blog – about LISP, through Common LISP. Testing the plist of a Symbol, is very straightforward in practice.

I have gone further with the present posting, by just confirming what I already suspected. When we use a Symbol to store a Function, in fact this gets treated separately, and again does not get stored on the plist. The function-field could state that the Symbol stores a Compiled Function, or a List that needs to be Interpreted, according to which blocks of addresses it points to…

What I have noticed however, is that in the case of Predefined, Compiled Functions, meta-data does get stored on the plist, which allows the LISP Compiler to act more, as Compilers do, for languages intended to be procedural in style. LISP was originally intended for declarative-style programming, but to be able to compile each function, it was necessary to standardize the way parameter-lists work, as well as return-types, conform to how they work in procedural languages such as C or C++.

In keeping with that, the plist of a Compiled, Predefined, Common LISP Function, contains templates, that state expected parameter-type-lists, just as C Function-Prototypes would have it.

But what seems to follow, is a flavor of LISP, which does not require the plist, in order for images to execute, and in order to be able to evaluate Lists. They only seem to be needed, to develop images and ‘LISP-Programs’.

The following code block shows, what happened in my most recent session…

Continue reading Common LISP has turned any Function a Symbol holds, into An Additional Field.

The Possibility of a Side-Register

The possibility can be considered, that in a certain implementation of LISP, a side-register on the CPU keeps track of what the data-type is, that the main register points to. But as the following experiment shows, this would only help accelerate how LISP expressions are evaluated, and does not affect how Common LISP in particular, stores the data-type in a variable. I.e., on the assumption that the data-type is held in a side-register, we could additionally assume that it gets inserted into the plist of a symbol, whenever we assign the value to the symbol. And what I have shown below, is that this additional assumption would be false, in the case of Common LISP:

Continue reading The Possibility of a Side-Register

A New Realization about Common LISP

In This Posting, I explored the potential fact in great depth, that certain implementations of LISP may have Symbols, one field of which holds a value in the sense that a variable should hold a value, consisting of lists and atoms, while another field can hold a property list, also known as a “Symbol Plist”.

Well it has come to my attention, that Common LISP in particular, has some fixed constraints regarding this subject.

When Common LISP evaluates expressions that are lists, the CAR is allowed to be a nested list, which defines a lambda-expression. But otherwise, the CAR needs to be an atom – i.e., a symbol – which has a compiled function, stored in the plist.

We may export function-definitions into the value-field of a symbol, such as into a variable, like so:

 


(defvar *function-var*
    #'(lambda (pos-arg1 pos-arg2)
        (list pos-arg1 pos-arg2) ) )

 

If we do, then we must call or apply this function like so:

 



(funcall *function-var* 'Foo 'Blatz)

(apply *function-var* '(Foo Blatz) )


 

If we do not abide by this convention, we get error messages, because the function-definition in the value-field is not searched by Common LISP, when the symbol is itself the CAR of a list, and because when we assign lists as function-definitions, those do not get assigned to the symbol plist.

This observation seems to be corroborated here.

This convention, of Common LISP, accelerates execution greatly, because the interpreter does not need to make complicated arrangements, depending on what type of functions appear as the CAR of a list. The context now specifies that.

Once we are aware that this constraint exists, adapting our value-field-functions to it, is straightforward, because of the built-in function

(symbol-function 'symbol)

Which disembodies the part of the plist, that is supposed to hold functions and not values, in this case, belonging to 'symbol. Hence, the following experiment should succeed on a working Common LISP Compiler:

 



GCL (GNU Common Lisp)  2.6.12 CLtL1    Oct 28 2014 10:02:30
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License:  GPL due to GPL'ed components: (XGCL READLINE UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/

>(setf (symbol-function 'my-function)
    (lambda (pos-arg1 pos-arg2)
        (list pos-arg1 pos-arg2) ) )

(LAMBDA-CLOSURE () () () (POS-ARG1 POS-ARG2) (LIST POS-ARG1 POS-ARG2))

>(my-function 'Foo 'Blatz)

(FOO BLATZ)

>(my-function 'Ergo 'Sum)

(ERGO SUM)

>(quit)


 

Now, the somewhat unexpected line output from the definition, is due to the (setf) function doing what all variable-setting functions in LISP do: They not only bind the value asked for, to the field, but also return the same value to the calling context, because doing so can make certain LISP code more practical.

Continue reading A New Realization about Common LISP

Alists and Plists

One of the data-structures that even early LISP implementations possessed, were ‘plists‘. It was only by reading up on LISP lately, that I discovered that many LISP implementations maintained a hidden plist, in which certain Properties of Symbols were stored. This could easily have been found in the CIR of the Atom, the naming of which was later simplified to CDR. Alternatively, this plist could have been the only datum of the Symbol, hence stored at its CAR.

In short, this was an early associative list, consisting of Key:Value pairs, where the Key was supplied by the programmer, in order to retrieve the Value from the plist.

Plists were later superseded by ‘alists‘. An alist has a better storage format, but again stores Key:Value associations. One big advantage of an alist, is the ability to perform a reverse look-up, in which a sought Value is supplied, and the List of Keys returned, that point to this Value.

I think it is agreed, that Hash Tables eventually manage forward-look-ups better than either a plist or an alist, especially if large numbers of Keys are stored. Yet, it is written that for short collections of data, the simplicity with which an alist is stored, actually allows it to work more quickly than a Hash Table, in LISP.

Now, if it was necessary to perform reverse look-ups, yet the large number of objects require a Hash Table, then the most sensible approach might be to create two Hash Tables, one for the forward look-up, and another for the reverse look-up? In that case, if a Hash Table is predicted to serve a one-to-many relationship, then the care should also be taken from the beginning, to encapsulate all the value-sets that result from one Key, into Sets, even if in many cases, there may be only one element in the Set.

Alternatively a system could be devised, so that only one result from the reverse look-up is the correct one.

Dirk