I am trying to shadow the mathematical operators in the CL package. Except for *, / and +, this works fine. However the symbol-value of those symbols are set by the implementation to values that I use frequently at the REPL (the function is interactive-eval in SBCL).
Since they're set in the previous form evaluation, I can't get at them except through the symbol in the CL package, i.e. cl:*, after the form is evaluated. I thought about making * a symbol macro that would dispatch on either my vectorised version of *, if in a function context, or return the value of cl:* otherwise.
However there doesn't seem to be an easy way to determine whether the symbol is being used as a function or value.
A stylised version of what I've got so far is:
(in-package :my-math-package)
(setf (fdefinition '+) #'my-vectorised-version-of-+)`
Since my version of the + function is a superset of CL's, everything works fine, except for trying to use * at the REPL whilst in my package. I could use cl:* and it works, but I'm trying to keep cl:* and my-package:* value slots synced.
One analogy for the symbol value might be:
(setf (symbol-value '+) #'cl:+)
But that doesn't work for two reasons:
When compiling cl:* has no symbol value
Even if it did, it would not have the current value of the last evaluated form, it would have a 'snapshot' of the value of cl:* at the time.
So I need to dynamically keep my-package:* and cl:* to have the same symbol-value.
Anyone have any ideas? Am I missing something obvious?
This is a classic edge-case of the package system in CL. However for most purposes a symbol macro will do just what you want.
As an example, if I'm in a package where * is not cl:* then I can, for instance, say this:
(defun * (a b)
(+ a b))
(define-symbol-macro * cl:*)
And now
> (* 1 2)
3
> *
3
> (funcall #'* 3 4)
7
> *
7
This is because symbol macros affect references to symbols for value not references for their function definition.
What you will lose is the ability to bind * and have that binding be special, because you can't declare symbol macros special. So
> (funcall (let ((* 2))
(lambda () *)))
2
for instance. That's probably not a huge problem for *.
More significantly you will also lose any places where * is used just as a symbol. For instance (declare (type (array * (* *))) ...) is no longer going to work, at all. There is nothing you can do about this because these are simply uses of * as a symbol. This is an inherent limitation of the package system.
As an aside: if you overload the operators of the field of numbers (so * and +) you probably want to think much harder about consistency than people usually do. Or just give up on consistency, which is what people normally seem to do. In particular (+) should return the zero of the field and (*) should return the 1 of it. But ... which field?
Related
It appears that I can use setf to create special variables. For example, if I start the REPL and enter (setf x 123), a special variable x will be created. There is no error in CLISP and ECL. SBCL gives a warning (undefined variable: COMMON-LISP-USER::X), but creates the special variable anyway. Is setf a valid way to create special variables?
It is not valid to use setf to create new variables. The HyperSpec is pretty clear that setf is only intended to update existing variables:
setf changes the value of place to be newvalue.
(setf place newvalue) expands into an update form that stores the result of evaluating newvalue into the location referred to by place.
setf is intended for updating a place. There is no behavior specified for attempting to use setf to update the value of a place that does not already exist.
In the section which discusses assignment, CLTL2 says a bit more:
Such alteration is different from establishing a new binding. Constructs for establishing new bindings of variables are described in section 7.5.
While this may seem to work, you can't rely on it. It often works in REPLs, and it is fine if you want to use setf this way when playing around in a REPL, but you should not do this in any program.
Actually it is a bit tricky.
This is one of the things in Common Lisp which are underspecified. Unfortunately.
LispWorks:
CL-USER 61 > (setf foo 1)
1
CL-USER 62 > (defun bar () foo)
BAR
CL-USER 63 > (bar)
1
CL-USER 64 > (let ((foo 2))
(bar))
1
The last foo in the let is using lexical binding and thus there it is not assumed to be special.
In the forms (setf foo 1) and (defun bar () foo) the variable foo is assumed by the particular Lisp implementation to be special and it even could be declared to be special by setf (-> which most implementations don't).
Whether above let form returns 1 or 2 is unspecified in the Common Lisp language standard. Most implementations will return 1, though.
Next:
CL-USER 65 > (let ((foo 2))
(declare (special foo))
(bar))
2
Above we see that the use of foo inside bar is actually using the dynamic binding of foo in the let.
Basically the exact effects of setting an undefined variable is unspecified. The variable could be assumed to be special or not. Most implementations prefer to NOT declare it special, such that further use of the variable must be special.
But whether the variable is special or not, and the exact effects using it, is actually undefined in the Common Lisp language standard.
Most implementations agree
that setf setting an undefined variable only changes the symbol value of the symbol
that setting and retrieving the variable is assuming a special variable
that rebinding the variable by let(or similar) does not create a special variable
that a compiler (if used) will warn about an undefined variable and/or about assuming a special variable.
One implementation where the default disagrees is CMUCL -> there the setf also declares the variable to be special, similar to what defparameter would do.
For a general style rule see the last paragraph of ad absurdum's answer.
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.
In this code
(defun foo ()
. . .
(let ((bar (foo)))
(if bar
. . .)))
in the let line, let is only binding, right? It doesn't actually run foo. I assume foo is run (recursively) for the first time in the if statement, correct? If what I assume is correct, is there a way to have let actually execute foo and then assign the results to bar?
There's an answer that shows an example that illustrates the behavior of let. However, an example via an implementation doesn't answer conclusively whether it's supposed to behave that way, or whether implementations are free to do different things, or whether there's a bug in the implementation. To know what's supposed to happen, you need to check the documentation. Fortunately, the Common Lisp HyperSpec is freely available online. The documentation for let says:
Special Operator LET, LET*
let and let* create new variable bindings and execute a series of
forms that use these bindings. let performs the bindings in parallel
and let* does them sequentially.
The form
(let ((var1 init-form-1)
(var2 init-form-2)
...
(varm init-form-m))
declaration1
declaration2
...
declarationp
form1
form2
...
formn)
first evaluates the expressions init-form-1, init-form-2, and so on,
in that order, saving the resulting values. Then all of the variables
varj are bound to the corresponding values; each binding is lexical
unless there is a special declaration to the contrary. The expressions
formk are then evaluated in order; the values of all but the last are
discarded (that is, the body of a let is an implicit progn).
Thus, all the forms are evaluated (executed), then the results are bound the values, and then the forms in the body are evaluated.
In the example you provided, foo is evaluated and then assigned to bar. You can test this by simply evaluating something like:
(let ((foo (+ 1 2)))
(if (= foo 3)
foo
nil))
; => 3
cf. PCL: Syntax and Semantics or Lispdoc.
Edit
As #paulo-madeira brought up in the comments, this is not enough to test, since you don't know when each one was evaluated. See his comment for a way to test it using FORMAT. Anyway, the takeaway is, the LET you propose evaluates foo and assigns it to bar, which means your function foo is defined in terms of itself, which means you're up to no good.
I know that when you want to make a dynamic/global binding in Lisp, you use either defparameter or defvar. I also know that you can make lexical bindings, well, almost everywhere, using defun argument lists or let statements.
What I'm wondering is what exactly it is I make when I make a statement like this where x was not declared or used anywhere else in the code:
(setf x 10 )
This appears to work fine, and x doesn't seem to behave like a lexical variable. Is it actually a dynamic global, the same as if I'd used defparameter or defvar, or is it something else entirely?
What it actually does is unspecified in the ANSI Common Lisp standard.
Generally I prefer any CL implementation to just set the dynamically bound value or global value. It should not to do anything else. CMUCL by default seemed to think that it was a good idea to declare the symbol special then. But that was a bad idea, since there was no obvious way to get rid of a global special declaration.
So, typically I would expect something like this (here, LispWorks):
CL-USER 66 > (defun foo () (setf x44 10))
FOO
The global variable is still unbound:
CL-USER 67 > x44
Error: The variable X44 is unbound.
1 (continue) Try evaluating X44 again.
2 Specify a value to use this time instead of evaluating X44.
3 Specify a value to set X44 to.
4 (abort) Return to level 0.
5 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
CL-USER 68 : 1 > :top
Let's call the function:
CL-USER 69 > (foo)
10
Now it has a global value:
CL-USER 70 > x44
10
But the variable is not declared to be special (as it would be by DEFVAR or DEFPARAMETER). Here a lexical binding is established.
CL-USER 71 > (let ((x44 20)) (foo) x44)
20
When we declare the local variable to be special, then our function changes the binding:
CL-USER 72 > (let ((x44 20)) (declare (special x44)) (foo) x44)
10
Very shortly, you can think of setq, which is the expansion of setf you have observed, as doing only one half of what defvar or defparameter do:
Consider that defparameter does this:
(declaim (special x))
(setq x 10)
I.e. it both provides some meta-data (the data about what sort of thing x is) to the compiler (in this case it tells it that it is a "special" variable) and assigns value.
In particular, defvar will not behave like this, if it is a top-level form. The standard behaviour is to initialize the value-cell of the symbol only once, so its code will be even more complex, something that you can think of as:
(unless (boundp x) ; This is not entirely correct, because if the symbol
; is otherwise known to the environment, but is unbound
; defvar will not re-bind it, but I can't think of a way
; to mimic that behavior
(declaim (special x))
(setq x 10))
The meta-data provided to compiler may or may not have any effect on how the code will behave. In general, the meta-data is supposed to aid the compiler to make better judgement of the intent behind your code, and thus may result in optimizations. But it can also be useful for documentation or debugging.
You can read about special and declare in Hyperspec.
As far as i know you should avoid using setf(which expands to setq) with undeclared variables. The behavior can differ between implementations and even if your code in REPL works good, the compiled program can be bugged in unexpected place. You can see warning in clisp if you do something like this:
>(defun internal-setf () (setf some-var 10))
>(compile 'internal-setf)
WARNING: in INTERNAL-SETF : SOME-VAR is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
I'm fairly new to lisp but I've been playing around with it. I have several problems which I need clarifying. Below is my little macro that I defined.
(defmacro transform (query)
'(lambda (row)
(eq (nth 1 query) (nth 0 (nth 0 row)))
)
)
I'm just wondering how I can specify the function to use in the body dynamically? Say if I want to use the "+" or "-" function instead of "eq", or even another function that I defined? Like I thought it'd be possible to pass in the name of the function as a parameter but that obviously doesn't work. I also get variable unbound errors when I modify the list (query) that's passed in.
In the body of the macro, you can use all of Lisp's run-time library to generate the actual expansion. So, for example:
(defmacro transform (query &key (test 'eq))
(let ((row-var (gensym)))
`(lambda (,row-var)
(,test (nth 1 ,query) (nth 0 (nth 0 ,row-var))))))
This version uses the "backtick" instead of a plain apostrophe, which allows for "unquoting" of forms within the body, thus allowing the inclusion of generated forms into the result.
You can use this macro like your original version:
(transform (...))
or (passing an explicit test function):
(transform (...) :test equal)
Note, that you should not use plain symbols as variable names in macro expansions (as your row argument to the generated lambda expression) as that might accidentally interfer with the use of that symbol at the site of the use of your macro. You simply don't know when writing your macro, whether there will be a variable called row somewhere when your macro is used, and whether it is not already used within the query form/expression. Your original definition would "capture" the variable, possibly altering the meaning of whatever query does.
funcall is the answer! Decided to just pass it in and use funcall to evaluate the function.