How to define globally a user input as variable - common-lisp

Is there a way, in common lisp, to receive a user input, say "foo", and defvar a global variable *foo*?
For example (which does NOT work):
(defun global-name (s)
"Takes s and changes it to *s*"
(concatenate 'string "*" s "*"))
(defun add-global-var (var)
"defvars a global variable and adds it to *global-list*"
(let ((var-name (global-name var)))
(defvar var-name var)
(push var-name *global-list*)))
; Used like this:
(add-global-var "myvar")
In this case, the var-name is a string, and will not work with defvar.

Déjà vu... I asked these kinds of questions 20+ years ago ;-)
Your question
Yes, you can do that (but no, you do not want to!)
(defun add-global-var (var-name &optional (package *package*))
(let ((var (intern var-name package)))
(proclaim `(special ,var))
(push var *global-list*)))
Please see
proclaim
intern
*package*
Alternatively, you can use a macro as the other answer suggests - in
fact, symbol creation at macroexpansion time (which is part of
compilation) is a very common thing,
cf. gensym.
Your problem
There is little reason to do this though.
Global variables created at run time were not available at compile time
and are, therefore, pretty useless.
Why do you want to do this?
If you want to map strings to values, you are much better off using an
equal hash table.
If you want to integrate with read,
you should call it while binding
*package*
to your internal temp package and then use
symbol-value
to store and retrieve values.
You will use intern to
map "variable names" to the symbols.

This is most likely a XY problem since it's very unusual to need to make a variable with a name made up in runtime. It's very common in compile time, but not runtime. #coredump has already covered compile time macros if that is what you are after.
Here is how you do it though:
(defun add-global-var (var)
"defvars a global variable and adds it to *global-list*"
(let ((var-name (intern (string-upcase (global-name var)))))
(set var-name var)
(push var-name *global-list*)))
set is deprecated, but I doubt it will ever be removed. Implementations might not be able to run as fast though since this is like messing with internals.
Since the names are not from source you you have no good use for the bidnings. because of this I would rather use a hash:
(defvar *bindings* (make-hash-table :test #'eq))
(defun add-binding (var)
(let ((var-name (intern (string-upcase (global-name var)))))
(setf (gethash var-name *bindings*) var)
*bindings*))
A reason to do this is as a part of your own little interpreter symbol table or something. You don't need a list of them since you can get all the keys from the hash as well as get the bound values.

Yes, with a macro:
(defvar *global-list* nil)
I changed global-name so that it also accepts symbols, to avoid thinking about whether the string should be upcased or not. With a symbol, the case is given by readtable-case (you can use uninterned symbols if you want to avoid polluting packages).
(defun global-name (name)
(check-type name (or string symbol))
(intern
(concatenate 'string "*" (string name) "*")))
I named the macro defvar*:
(defmacro defvar* (name)
`(push
(defvar ,(global-name name) ',name)
*global-list*))
Tests:
CL-USER> (defvar* #:foo)
(*FOO*)
CL-USER> (defvar* #:bar)
(*BAR* *FOO*)
Note:
You can also add an optional package argument like in #sds's answer, that's better.

Related

Good example of when to muffle warnings?

This question is somewhat related to an earlier one on programmatically generating symbol macros. I'm using that function in a convenience macro that throws undefined variable warnings. This macro and function:
(defmacro define-data (d body &optional doc)
(if (and doc (not (stringp doc))) (error "Documentation is not a string"))
`(let* ((d-str (string ',d))
(old-package *package*)
(*package* (if (find-package d-str) ;exists?
(find-package d-str) ;yes, return it
(make-package d-str)))) ;no, make it
;; Should we have an eval-when (:compile-toplevel) here?
(defparameter ,d ,body ,doc)
(export ',d old-package)
(define-column-names ,d)))
(defun define-column-names (d)
(maphash #'(lambda (key index)
(eval `(cl:define-symbol-macro ,key (cl:aref (columns ,d) ,index))))
(ordered-keys-table (slot-value d 'ordered-keys))))
are intended to be like defparameter, but additionally set up a few niceties for the user by defining:
a package with the name of d
a parameter in the current package with the data that will be sucked in by body
symbol-macros in package d for access to the individual data vectors
If I use defparameter from the REPL, and then call define-column-names, all is well. However when using the macro I get:
; in: DEFINE-COLUMN-NAMES FOO
; (DEFINE-COLUMN-NAMES CL-USER::FOO)
;
; caught WARNING:
; undefined variable: CL-USER::FOO
I suspect that this is because the compiler has no way of knowing that FOO will actually be defined when define-symbol-macro is called. Everything works fine, but I don't want the warning to frighten users, so am thinking of suppressing it. I hate suppressing warnings though, so thought I'd come here for a second opinion.
EDIT: I've marked an answer correct because it does correctly answer the question as asked. For an answer to the problem see my comments.
My answer to the 'when to muffle warnings' question in the title is: if it's your own code then never, under any circumstances. If it is someone else's code, then rewrite it not to warn unless you can't.
As to solving the problem I haven't thought about this hard enough, but the problem is that you definitely want the defparameter to be at top-level so the compiler can see it, and it can't really be if it's inside a let. But you can raise it to toplevel trivially since it depends on nothing inside the let.
I am then pretty certain that you want the rest of the macro to happen at compile time, because you definitely want the symbol-macros available at compile-time. So an attempt at the first macro would be (note I've fixed the handling of the docstring: (defparameter foo 1 nil) is bad):
(defmacro define-data (d body &optional doc)
(when (and doc (not (stringp doc)))
(error "Documentation is not a string"))
`(progn
(defparameter ,d ,body ,#(if doc (list doc) '()))
(eval-when (:compile-toplevel :load-toplevel :execute)
(let* ((d-str (string ',d))
(old-package *package*)
(*package* (if (find-package d-str) ;exists?
(find-package d-str) ;yes, return it
(make-package d-str)))) ;no, make it
(export ',d old-package)
(define-column-names ,d)))))
As a side note: although I think the fact that programmatically defining symbol macros is hard because CL left that out for some reason, I think I'd personally use some other approach rather than this, because eval is just so horrid. That's just me however: if you want to do this you do need eval I think (it is very rare that this is true!).
I am not sure exactly how define-columns-names works so I replaced it with a stub function that returns d.
Note also that you can use check-type and should try not injecting symbols in generated code, this introduces potential variable capture that can be avoided with gensym.
As far as I know you cannot use eval-when as suggested by your comment (see Issue EVAL-WHEN-NON-TOP-LEVEL Writeup for details).
But I have no warning if I declare the symbol as being special around the call.
(defmacro define-data (d body &optional doc)
(check-type doc (or null string))
(check-type d symbol)
(let ((d-str (string d)))
(alexandria:with-gensyms (old-package)
`(let* ((,old-package *package*)
(*package* (if (find-package ,d-str) ;exists?
(find-package ,d-str) ;yes, return it
(make-package ,d-str)))) ;no, make it
(defparameter ,d ,body ,doc)
(export ',d ,old-package)
(locally (declare (special ,d))
(define-column-names ,d))))))
It is also a bit strange that you expand into a call to define-column-names, which in turns evaluated a form built at runtime. I think it might be possible to do all you want during macroexpansion time, but as said earlier what you are trying to do is a bit unclear to me. What I have in mind is to replace define-column-names by:
,#(expand-column-names-macros d)
... where expand-column-names-macros builds a list of define-symbol-macro forms.

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.

Neither a function nor a macro would do

Consider this question. Here the basic problem is the code:
(progv '(op arg) '(1+ 1)
(eval '(op arg)))
The problem here is that progv binds the value to the variable as variable's symbol-value not symbol-function. But, that's obvious because we didn't explicitly suggest which values are functions.
The Plan
So, in order to solve this problem, I thought of manually dynamically binding the variables, to their values based on the type of values. If the values are fboundp then they should be bound to the symbol-function of the variable. A restriction, is that match-if can't be a macro. It has to be a function, because it is called by a funcall.
Macro : functioner:
(defmacro functioner (var val)
`(if (and (symbolp ',val)
(fboundp ',val))
(setf (symbol-function ',var) #',val)
(setf ,var ,val)))
Function: match-if:
(defun match-if (pattern input bindings)
(eval `(and (let ,(mapcar #'(lambda (x) (list (car x))) bindings)
(declare (special ,# (mapcar #'car bindings)))
(loop for i in ',bindings
do (eval `(functioner ,(first i) ,(rest i))))
(eval (second (first ,pattern))))
(pat-match (rest ,pattern) ,input ,bindings))))
Here, the let part declares all the variables lexically (supposedly). Then declare declares them special. Then functioner binds the variables and their values aptly. Then the code in the pattern is evaluated. If the code part is true, then only the pattern-matcher function pat-match is invoked.
The Problem
The problem is that in the function, all it's arguments are evaluated. Thus bindings in the let and declare parts will be replaced by something like :
((v1 . val1)(v2 . val2)(v3 . val3))
not
'((v1 . val1)(v2 . val2)(v3 . val3))
So, it's treated as code, not a list.
So, I'm stuck here. And macros won't help me on this one.
Any help appreciated.
Not the answer you are looking for, but PROGV is a special operator; it is granted the ability to modify the dynamic bindings of variables at runtime; AFAIK, you can't simply hack it to operate on "dynamic function bindings".
The point of progv is to use list of symbols and values that are evaluated, meaning that you can generate symbols at runtime and bind them dynamically to the corresponding values.
You might be able to find a solution with eval but note that if you macroexpand into (eval ...), then you loose the surrounding lexical context, which is generally not what you want ("eval" operates on the null lexical environment). I speculate that you could also have a custom code walker which works on top-level forms but reorganizes them, when it finds your special operator, to bring the context back in, producing something like (eval '(let (...) ...)).

Common Lisp: defpackage and exporting symbols that are created programmaticaly

how would you / should you export symbols from a package, when you have not yet created them at the time of calling the defpackage macro?
(defpackage :package-a
(:use :cl)
(:export :fruit-type :animal-type :orange :apple :peach :cat :dog))
(deftype fruit-type () '(member ORANGE APPLE PEACH))
(deftype animal-type () '(member CAT DOG))
(defparameter *other-symbol-names*
'("A1" "A2" "B1" "B2")) ;imagine a longer list here
;with names generated by a function
(defparameter *other-symbols*
(mapcar #'(lambda (sym-name)
(import (make-symbol sym-name))
(find-symbol sym-name))
*other-symbol-names*))
(mapcar #'export *other-symbols*)
(setf A1 32 A2 33 B1 34 B2 35)
also there is another package
(defpackage :package-b
(:use :cl :package-a))
(in-package :package-b)
(format nil "~a ~a ~a ~a" |A1| |A2| |B1| |B2|)
I have read in "The Complete Idiot’s Guide to Common Lisp Packages" that
"Now that you’ve learned all about the myriad functions and macros that can be
used to manipulate packages you shouldn’t really be using any of them. Instead,
all of the functionality of IMPORT, EXPORT, SHADOW, etc. is all rolled up in a
single macro called DEFPACKAGE, which is what you should use for real (non-
prototype) code."
Is there a code smell in my above code? Also, how would you export the other symbols (cat dog animal-type, etc. -- there are many of them) to avoid duplication?
It's hard to say much without knowing more about your intent and requirements, but in many situations it would be better to have one or more hash tables (or similar) which contain your dynamically generated objects, and then export symbol(s) for your hash table(s).
Here's a hand-wavy example of how this can work. If you can edit and add some more information about your requirements and constraints I'll see if I can be more help.
(in-package :cl)
(defpackage :package-a
(:use :cl)
(:export *objects* put get)
(:shadow get))
(in-package :package-a)
(defvar *objects* (make-hash-table)
"Container for dynamically generated objects we want to expose to the
package's user.")
(defun put (name obj)
(setf (gethash name *objects*) obj))
(defun get (name &optional default)
(gethash name *objects* default))
;; Your code can put arbitrary objects into the hash table
(put :foo (lambda () :a-thunk))
(put :bar (lambda () :another))
;; And your users can retrieve them
(in-package :cl-user)
(use-package :package-a)
(funcall (get :foo)) ;; => :a-thunk
I used keywords for the names rather than symbols because keywords aren't local to packages (or, more specifically, they're all local to the keyword package. If you were to instead use 'foo and 'bar you'd be back to needing to export those symbols, or your user would need to use the package designator when refer to them (e.g. (get 'package-a::foo)).
You can also use strings as keys, though in that case you would want to create the table with (make-hash-table :test 'equal). The default hash table test is #'eql, which doesn't compare strings appropriately. Comparing keywords with #'eql is faster than comparing strings with #'equal (because keywords are a simple pointer comparison, as opposed to the character-by-character comparison necessary for strings) but the difference is likely insignificant unless you have specific reason to think otherwise.
This approach provides a better interface for your users, because now your have defined entry points, the opportunity for docstrings, defaults, and easier exploration at the REPL.

Defining a variable with a name that is kept in an other variable

I need to define a variable with a name contained in another variable.
The following code does not work and it uses eval, therefore not very good style.
(defvar symbol "zap")
(eval `(defvar ,symbol 100))
(print zap)
It's usually better to use a hash table for that purpose.
First of all -- are you sure you need to do this?
Now, with that out of the way --
(defvar *symbol-name* "zap")
(let ((symbol (intern *symbol-name*)))
(proclaim `(special ,symbol))
(setf (symbol-value symbol) 100))
(print |zap|)
Note that |zap| will normally need to be quoted with pipes, because intern is case-sensitive, while the default readtable upcases symbols by default. So if you don't quote, as in (print zap), that is interpreted as (PRINT ZAP), with the wrong case for zap. Alternatively, you can upcase the interned symbol, with (intern (string-upcase *symbol-name*)).
Update after seeing what you're actually trying to do.
You definitely don't want to be defining global variables for that. A data structure that maps keys (A1...H4, etc) to numbers is what you want. In this case, your keys can be symbols or strings. And the data structure could be a hashtable, a plist or alist (among other choices). For example, a string-keyed hashtable would look like:
(defvar *table* (make-hash-table :test #'equalp))
(setf (gethash "A1" *table*) 42)
(print (gethash "A1" *table*)) ==> prints 42
If you absolutely want to do this, with global variables, I suspect that SET and SYMBOL-VALUE (and using symbols instead of strings) might do the trick. It definitely falls in the "hm, yes, you can do it that way, but I am not convinced it's the best way" territory, though.
However, you are most probably better off either using a hash-table or (skipping storage completely, if there's no need to mutate what A1 means further down the line) a function that parses the letter and digit apart and calculates the relevant value.
use SET:
CL-USER 13 > (defvar *some-symbol* '*this-is-some-symbol*)
*SOME-SYMBOL*
CL-USER 14 > (set *some-symbol* 42)
42
CL-USER 15 > *this-is-some-symbol*
42
or if it is a string:
(setf (symbol-value (find-symbol some-symbol-name)) 42)

Resources