deal with readtable case when building symbols inside a macro - common-lisp

I want to build a macro that defines several classes and methods based on symbols that would have a root string (I guess this is not an unusual thing to do in lisp ^^).
dummy example :
(defmacro define-my-stuff (term)
would do such things as
defclass my-super-term-class
defvar *term-variable*
defun do-term ((a-thing *example-term*))
with symbols built upon the "term" macro parameter
How to deal with the different readtable-case so the code can be universally used with the four different type of cases (:UPCASE :DOWNCASE :PRESERVE :INVERT).
I want to be able to use these symbols from source code. So I want the symbols created inside the macro to be built by the reader readtable-case rule that is used by the lisp system.
(The regular is :UPCASE but some uses :DOWNCASE for example).
The only way I have found to do such a thing would be to use the READ-FROM-STRING function (example : (read-from-string (concatenate "term" "-variable"))
But this also interns the symbol as side effect.
So how should I compute a symbol following the readtable-case rule without interning it ?
Is there in function for that in the common-lisp package ?

You can use an uninterned symbol as a string designator:
(string '#:Foo)
=> "FOO"
or=> "foo"
or=> "Foo"
or=> "fOO"

You can create an uninterned symbol:
(read-from-string (concatenate 'string "#:" "term" "-variable")
But you need to be very careful with READ-FROM-STRING when trying to securely read from a not secure string. Common Lisp IIRC lacks a standard symbol parser which only does that operation in isolation - without read time evaluation and without reading arbitrary structures. There is probably in a library somewhere a 'secure' symbol parser, which the also checks the readtable case.

Related

Why do we specifiy packages using pound colon in Common Lisp?

New Common Lisper here. I have seen packages being declared with the pound colon syntax, as in (defpackage #:foo), but I have also seen them defined as plain keywords, as (defpackage :foo).
Which is considered "better"? What is the difference between these two? I read somewhere that pound colon simply means the keyword isn't interned. Is that true? If so, what are the advantages to defining a package with an uninterned keyword?
Package names are strings, but you can designate them using symbols, so you have basically the following options:
1. (defpackage foo ...)
2. (defpackage "FOO" ...)
3. (defpackage :foo ...)
4. (defpackage #:foo ...)
It is true that #:foo is an uninterned symbol, and the reason some people prefer to use that syntax is precisely because it does not "pollute" the current package (1) or the keyword package (3). Usually (1) is a big No because your defpackage form has a side-effect on whatever package is current, which is bad. At least (3) is more deterministic, you always pollute the keyword package.
Note that "polluting" is not so much a problem of having too many symbols in a package, but also the fact that it is harder to reverse the operation: delete-package cleans the package designated by the symbol, but there is still a symbol interned in another package that probably was not there before defpackage (and if it already was there, you don't want to unintern it).
Some people don't mind and use keyword symbols everywhere, and it is not "bad", it just has a potential for being a source of problems in some corner cases. It is usually better to use either a string (2) or an uninterned symbol (4).
The advantage of strings over symbols (interned or not) is that you control the case: it is possible to have different packages with names that are only distinct in case (e.g. "test" vs "TEST"), and while the standard defines how symbols are read by default (upcased), you don't know in advance if your package definition will be read by a Lisp environment that is setup in a standard way or a custom way (e.g. inverting the case before interning).
So ideally it should be more robust to use always literal strings: they do not intern a symbol and the case is explicit.
However, for some reason people tend to prefer writing #:foo: probably because it is not written in uppercase, or because there is no need for quotes, etc. I am not sure why honestly (strings are often a code smell in other circumstances so maybe we tend to avoid them).
Anyway, it has become a bit customary to use uninterned symbols. This is usually not a problem because (i) people tend to use the standard readtable and (ii) in case they customize it, it is quite stable during the execution of a Lisp environment: whether you upcase or downcase the symbol in the defpackage of some package P, the symbol will be read the same way in the (:use P) clause of another defpackage.
Package names are strings. But it is a good idea to specify them as symbols, because this buys you immunity to variants of CL which which do not have the same case behaviour as CL. As an example, Allegro CL has (or used to have: I have not looked at it for at least a decade) a mode where everything was lower-case by default. In that mode (symbol-name 'foo) would be "foo", and all the standard CL symbols were lower-case versions of themselves (so (symbol-name 'symbol-name) was "symbol-name".
If you wanted to write code which had any chance of running in an environment like that, you couldn't give packages names which were strings:
(defpackage "FOO"
...)
would mean that, in future, you'd need to type FOO:x and so on, which was horrible. Even worse, if you said
(defpackage "FOO"
...
(:export "X"))
You'd now have to type FOO:X. And something like this:
(defpackage "FOO"
(:use "CL")
(:export "X"))
would fail dismally because there was no package whose name was "CL" at all: its name, of course, was "cl".
So if you needed things to work with that environment you really wanted to type package names – and symbol names in packages – as symbols.
This also would mean that your code would have a chance of running in some future CL variant which really was lower-case, which many people assumed would probably happen at some point, since case-sensitive lower-case-preferred languages had clearly won by the late 1980s.
Given that there's a question of where you want the names to be interned. For symbols in a package it is generally very undesirable to intern them in the current package:
(defpackage foo
(:export x y z))
(use-package 'foo)
will fail.
So then there are two obvious choices:
intern things in the keyword package;
don't intern them.
It does not make much difference which you do in practice. Personally I intern package names in the keyword package as I want completion to work on them, but do not intern symbol names, because that seems just to be gratuitous clutter. So my package definitions look like
(defpackage :foo
(:use :cl ...)
(:export #:x #:y ...))

Usefulness/point of function "symbol-name"?

On first look it seems somewhat silly to have a function which returns the name of a symbol, which must be called using the name of that same symbol. i.e. it should already be obvious in the calling context what the function will return. On the other hand there is identity which is sometimes useful (I forget where just now) but I supposed (perhaps wrongly) that symbol-function is there for a reason other than simply to act as a kind of identity.
However, the hyperspec offers a possible hint:
(symbol-name 'temp) => "TEMP"
(symbol-name :start) => "START"
(symbol-name (gensym)) => "G1234" ;for example
I note that :start means get the name of the symbol start from the keyword package, where the keyword package is denoted simply by :.
(:keyword being its longer form, unnecessary to use). Thus, in this case symbol-name plays the role of simply removing the package prefix.
The other thing it might do is, given an implementation is case insensitive, it would get the actual name by removing case in the symbol name supplied.
Is that roughly it or is there any importance to this function I am missing?
One thing I was confused by about symbols (cleared up now) is that symbol-plist does not tell you everything about the symbol (say, whether it holds the value of a special variable or function). Rather, plist is a mainly legacy feature now largely replaced by hashtables. So, a call to symbol-plist is going to return NIL even if one has set a special variable on the symbol.
One final question on that, Paul Graham says in Chapter 8 (p133), that "You can use symbols as data objects and as names for things without understanding how the two are related". Would it be correct say that if we rarely now use plists, that, today, we generally don't use symbols "as data objects" at all, instead, just as names for things (allbeit with the duality in CL of course, i.e. symbol-function and symbol-value simultaneously).
Symbols are objects. You can create them and pass them around programmatically. One of the properties of these objects is their name, which is a string. Symbol-name is the reader (not accessor) for that. That's all.
Symbols are also used in the representation of code. In this case, they are created by the reader and used by the compiler. This is not their only use, however, and the spec makes no such assumptions either. I hope that this addresses the core of your question.
Here is a function that, given a symbol, returns a symbol interned in the same package but with a reversed name:
(defun reverse-symbol (symbol)
(intern (make-symbol (reverse (symbol-name symbol)))
(symbol-package symbol)))
Here is a function that, given a string designator, returns the designated string:
(defun designated-string (string-designator)
(ctypecase string-designator
(string string-designator)
(symbol (symbol-name string-designator))))
You can also do all kinds of shenanigans in macros and compiler macros by inspecting the names of the symbols in the given form and applying some conventions (not that you should…).
Let's assume you want to write some protocol for transmitting bits of structure between two different systems over some serial channel
(defgeneric transmit-object (o stream))
What is the method for symbols going to look like?
(defmethod transmit-object ((o symbol) stream)
... (symbol-name o) ...)
In particular you certainly do not know the name of the symbol at the point where you need to reason about it, and you could not write such a protocol without using symbol-name (or some absolutely appalling hack like printing the symbol to a string and using that).
Regarding symbol-plist, the implementation is completely at liberty to keep all sorts of information on the property list of a symbol. I am not even sure that the implementation is not allowed to do (a cleverer version of):
(defun symbol-value (s)
(let* ((d (load-time-value (cons nil nil)))
(v (get s secret-value-indicator d)))
(when (eq v d)
(error ...))
v))
It may be that this is not allowed, but I am not sure. Certainly it was once fairly common for function definitions to be kept in this way.
It's not so silly when you process symbol names. When you for example build preprocessor - you read some data, convert it to list structures and then some code is processing those list and trigger some additional logic when symbol-name is lets say defun-my-ubermacro. It's exactly what's in Graham quote - you treat symbols as data.
And (in my opinion) it's not correct to say, that when you don't use plists, you generally don't use symbols as data. Plists are only on of many places where it's useful feature. A lot of what macros do is processing symbols as data / names.
On first look it seems somewhat silly to have a function which returns the name of a symbol, which must be called using the name of that same symbol.
That's wrong. symbol-name is called with a symbol and not a name. It returns the name as a string.
I note that :start means get the name of the symbol start from the keyword package, where the keyword package is denoted simply by :. (:keyword being its longer form, unnecessary to use). Thus, in this case symbol-name plays the role of simply removing the package prefix.
No, symbol-name returns the name of the symbol as a string. The keyword symbol is an object of type symbol.
A symbol is a data type and has several cells:
the name, a string
possibly a function
possibly a value
a property list
optionally the home package it is interned in
don't use symbols "as data objects" at all, instead, just as names for things
No, symbols as data objects have many purposes. For example Lisp source code uses many symbols. But it can also appear in all sorts of data.
CL-USER 6 > 'foo
FOO
CL-USER 7 > (type-of 'foo)
SYMBOL
CL-USER 8 > (symbol-name 'foo)
"FOO"
CL-USER 9 > (type-of (symbol-name 'foo))
SIMPLE-BASE-STRING
CL-USER 10 > (mapcar #'symbol-name '(a b c defun foo bar))
("A" "B" "C" "DEFUN" "FOO" "BAR")
CL-USER 11 > (mapcar #'type-of *)
(SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING)
Since you haven't accepted an answer, here is my take.
For most day-to-day programming symbols, and therefore SYMBOL-NAME,
aren't very useful. Mostly they are used for their
unique-ness. However they shine when you are modifying the compiler
with macros.
Here are 3 examples where SYMBOL-NAME is used:
Firstly, LOOP is the CL generic looping construct, it works via
placeholder symbols in a way that some claim is un-lispy, but it
remains very handy, especially if you are stepping things in parallel.
The following 3 forms are equivalent (at run-time):
(loop for i in list collect i)
(loop :for i :in list :collect i)
(loop #:for i #:in list #:collect i)
I, personally, prefer the third form because it makes it really
obvious where the LOOP magic is happening, and also avoids interning
symbols in any package (which is usually harmless, but not
always). That the third works at all requires the existence of
SYMBOL-NAME
Secondly, I don't make much use of CLOS but classes are undeniably
useful. DEFCLASS tends to be too verbose for what I want to do though,
so I often employ a macro that uses implied symbols. So:
(defbean peer ()
(id)
(next
beats))
Becomes:
(defclass peer nil
((id :initarg :id :reader peer-id)
(next :initarg :next :accessor peer-next)
(beats :initarg :beats :accessor peer-beats)))
Saving much typing. Notice how the slot name is converted to a keyword
for the initargs, and how reader and accessor names are created.
Some don't like this sort of macro, and I can see how it might be
problematic if you have a large team with everyone doing this all over
the shop (though M-. and C-c ret are always available), but for
small teams I think this is one of the best reasons to use lisp,
customising it to how you actually want to use it.
Thirdly, my sqlite helper library uses SYMBOL-NAME to generate SQL
statements (along with some more implied symbols) for even more
code-saving:
(defsqlite-table artists
(id :auto-key)
(artist-name :t)
(sort-artist-name :t :n))
Becomes something pretty huge:
(progn
(defparameter +create-artists-sql+
"CREATE TABLE artists (
id INTEGER PRIMARY KEY NOT NULL,
artist_name TEXT NOT NULL,
sort_artist_name TEXT
)")
(defun create-artists-table (pjs-sqlite::db pjs-sqlite::recursive log)
###)
(eval-when (:load-toplevel)
###)
(defun insert-artists
(pjs-sqlite::db artist-name sort-artist-name &key (id nil id-p))
###)
(defun update-artists
(pjs-sqlite::db id
&key (artist-name nil artist-name-p)
(sort-artist-name nil sort-artist-name-p))
###)
(defun delete-artists (pjs-sqlite::db id)
(with-sqlite-statements (pjs-sqlite::db
(pjs-sqlite::stmt
"DELETE FROM artists WHERE id = ?"))
###)))
(I stripped out a lot of code that would be distracting, but it should
be clear how I mapped symbols to sql identifiers)
I hope this gives you some ideas on what sort of things SYMBOL-NAME
can be used for.

How to export all definition symbols in a file in Common Lisp?

My lisp file contains about 50 function and macro definitions. At the head of the file is:
(defpackage :utils
(:use :common-lisp))
(in-package :utils)
; ... ~50 defuns/defmacros follow along with some other code
I want to export all these 50 definitions. But no other symbols.
To write them all out in :export clauses inside defpackage seems very tedious.
I tried getting the necessary symbols by using loop's facility for listing symbols in a package. But both "symbol" and "present-symbol" don't output the needed definition symbols. I could somehow subtract "external-symbols" and inherited symbols. But this seems like the kind of thing everyone would need and there should be an established easy solution. I looked around and haven't found a straightforward answer.
How do I export all the definition symbols without having to write them out individually and manually?
scan symbols
You can scan all symbols and export all that have a function binding (this includes macro names):
(defun export-fbound-symbols (package)
"export symbols with function bindings"
(do-symbols (s package)
(when (fboundp s)
(export s package))))
This is usually not a very good idea: good software engineering practice is to limit the set of public interfaces.
be more selective
You can redefine defun and defmacro so that they automatically export their definienda.
See exporting.lisp in CLISP. E.g.,
(defmacro define-function (name lambda-list &body body)
`(progn
(export ',name)
(defun ,name ,lambda-list ,#body)))
Note that this ignores the possibility of (defun (setf foo) (...) ...).
No, this is not something everyone needs. Usually, you'd export them as you write (and actually need) them.
I'd probably use an ad hoc keyboard macro for this. You could also write a little Lisp function to read your file form by form and output the relevant symbols for copy-paste.

What's the meaning of "#+" in the code of cl-mysql? [duplicate]

This question already has answers here:
operator #+ and #- in .sbclrc
(2 answers)
Closed 6 years ago.
Recently I tried to read code about cl-mysql, but got stuck with the #+.
Tried to google it, but not work, so turn to here
(defun make-lock (name)
#+sb-thread (sb-thread:make-mutex :name name)
#+ecl (mp:make-lock :name name)
#+armedbear (ext:make-thread-lock)
#+ (and clisp mt) (mt:make-mutex :name name)
#+allegro (mp:make-process-lock :name name))
And looks like it is for different backend lisp compiler. But still no idea why write something like this.
Anyone can help me make it clear, thx.
#+ is a reader-macro that checks if a keyword is in the special variable *FEATURES*. If it isn't there, the following form will be skipped over (by the reader; the compiler will never see it). There is also #- which does the opposite.
There are some things that aren't part of the Common Lisp standard, but are important enough that all (or most) implementations provide a non-standard extension for them. When you want to use them in code that needs to work on multiple implementations, you have to use read-time conditionals to provide the correct code for the current implementation. Mutexes (and threads in general) are one of those things.
Of course there may be features provided by third party libraries as well. The contents of *FEATURES* will look something like this:
(:SWANK :QUICKLISP :SB-BSD-SOCKETS-ADDRINFO :ASDF-PACKAGE-SYSTEM :ASDF3.1
:ASDF3 :ASDF2 :ASDF :OS-UNIX :NON-BASE-CHARS-EXIST-P :ASDF-UNICODE :64-BIT
:64-BIT-REGISTERS :ALIEN-CALLBACKS :ANSI-CL :ASH-RIGHT-VOPS
:C-STACK-IS-CONTROL-STACK :COMMON-LISP :COMPARE-AND-SWAP-VOPS
:COMPLEX-FLOAT-VOPS :CYCLE-COUNTER :ELF :FLOAT-EQL-VOPS
:FP-AND-PC-STANDARD-SAVE :GENCGC :IEEE-FLOATING-POINT :INLINE-CONSTANTS
:INTEGER-EQL-VOP :INTERLEAVED-RAW-SLOTS :LARGEFILE :LINKAGE-TABLE :LINUX
:LITTLE-ENDIAN :MEMORY-BARRIER-VOPS :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLADDR
:OS-PROVIDES-DLOPEN :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL
:OS-PROVIDES-PUTWC :OS-PROVIDES-SUSECONDS-T :PACKAGE-LOCAL-NICKNAMES
:PRECISE-ARG-COUNT-ERROR :RAW-INSTANCE-INIT-VOPS :SB-DOC :SB-EVAL :SB-FUTEX
:SB-LDB :SB-PACKAGE-LOCKS :SB-SIMD-PACK :SB-SOURCE-LOCATIONS :SB-TEST
:SB-THREAD :SB-UNICODE :SBCL :STACK-ALLOCATABLE-CLOSURES
:STACK-ALLOCATABLE-FIXED-OBJECTS :STACK-ALLOCATABLE-LISTS
:STACK-ALLOCATABLE-VECTORS :STACK-GROWS-DOWNWARD-NOT-UPWARD :SYMBOL-INFO-VOPS
:UNIX :UNWIND-TO-FRAME-AND-CALL-VOP :X86-64)
So if you wanted to write code that depends on Quicklisp for example, you could use #+quicklisp. If you wanted code that is only run if Quicklisp is not available, you'd use #-quicklisp.
You can also use a boolean expression of features. For example,
#+(or sbcl ecl) (format t "Foo!")
would print Foo! on either SBCL or ECL.
#+(and sbcl quicklisp) (format t "Bar!")
would only print Bar! on SBCL that has Quicklisp available.
One could imagine that we can write:
(defun make-lock (name)
(cond ((member :sb-thread *features)
(sb-thread:make-mutex :name name))
((member :ecl *features*)
(mp:make-lock :name name))
...))
But that does usually not work, because we can't read symbols when their package is not existing and some packages are implementation/library/application specific. Packages are not created at read time in a lazy/automatic fashion.
In Common Lisp, reading a symbol of a package, which does not exist, leads to an error:
CL-USER 1 > (read-from-string "foo:bar")
Error: Reader cannot find package FOO.
1 (continue) Create the FOO package.
2 Use another package instead of FOO.
3 Try finding package FOO again.
4 (abort) Return to level 0.
5 Return to top loop level 0.
In your example sb-thread:make-mutex is a symbol which makes sense in SBCL, but not in Allegro CL. Additionally the package SB-THREAD does not exist in Allegro CL. Thus Allegro CL needs to be protected from reading it. In this case, the symbol sb-thread:make-mutex will only be read, if the the feature sb-thread is present on the cl:*features* list. Which is likely only for SBCL, or a Lisp which claims to have sb-threads available.
The feature expressions here prevents the Lisp from trying to read symbols with unknown packages - the packages are unknown, because the respective software is not loaded or not available.

Refer to symbol in another package not known at compile time in common-lisp

Is there a way to easily refer symbols in another other package without knowing it in advace ?
Let's say that I have a function like the following in a package names MY-PACKAGE
(defun foo-bar (foo bar)
`((,foo . foo)
(,bar . bar)))
If I call the above from the same package I'll get something like the following:
MY-PACKAGE> (foo-bar 1 2)
((FOO . 1) (BAR . 2))
If I call it from some other package, let's say CL-USER, the symbol returned refer to the package MY-PACKAGE:
CL-USER> (my-package:foo-bar 1 2)
((MY-PACKAGE:FOO . 1) (MY-PACKAGE:BAR . 2))
Sometimes, expecially when writing macros, I'd like to have the function return symbol interned in the package from which the function has been called (in this case CL-USER).
The only way I have been able to do this is by rewriting foo-bar as follows
(defun foo-bar (foo bar)
`((,(intern "FOO" *package*) . ,foo)
(,(intern "BAR" *package*) . ,bar)))
This gets ugly very soon, expecially when the symbols are given as parameters.
Is there any better way to handle this ?
Functions are not called from a package. Packages are only used by the reader and by symbol creating functions like INTERN. At call time the symbols of a function are already interned in the package where the source code was originally read. For the function itself is does not matter how you get it's symbol name and call it.
If you want to create symbols in different packages based on, say, the value of the variable *package*, then you have to say so. INTERN is the way to create new symbols and the package is a parameter. It is also possible to create symbols without interning them in a package.
If the package for the symbol does not matter, then one might want to use uninterned symbols or, typically, keyword symbols. Keyword symbols are interned in the package keyword and evaluate to themselves.
Using INTERN with *package* is fine if you really intend to intern the key symbol of the association list in a different package depending on the context. However, note that *package* may not be bound to the package of the call unless you bind it explicitly. You can resolve that by defining a macro instead of a function and use the *package* binding at macro expansion time.
If the symbols are given as parameters to the function call, they are likely already interned in the package of the function call. Hence there is no need to use INTERN.
In case you are open to alternative approaches, Rainer's answer provides good suggestions such as using keyword symbols like :foo and :bar instead.

Resources