As a part of a Tic Tac Toe playing bot, I need a function that evaluates combinations of tiles to points. The code would look something like this:
(case combination
("EEEEE" 0)
("EEEEP" 1)
("EEEPE" 1)
("EEEPP" 2)
("EEPEE" 1)
("EEPEP" 2)
("EEPPE" 2)
("EEPPP" 3)
("EPEEE" 1)
("EPEEP" 2)
("EPEPE" 2)
("EPEPP" 3)
("EPPEE" 2)
("EPPEP" 3)
("EPPPE" 3)
("EPPPP" 4)
("PEEEE" 1)
("PEEEP" 2)
("PEEPE" 2)
("PEEPP" 3)
("PEPEE" 2)
("PEPEP" 3)
("PEPPE" 3)
("PEPPP" 4)
("PPEEE" 2)
("PPEEP" 3)
("PPEPE" 3)
("PPEPP" 4)
("PPPEE" 3)
("PPPEP" 4)
("PPPPE" 4)
("PPPPP" 5))
(This is not the place to discuss the value of such an approach, for it is used for reasons unrelated to the question)
The problem is that case uses a predicate that doesn't return true for identical strings that aren't the same object (hard to find if it's eq or eql). How can you change that?
EDIT: I solved the original problem by converting the string into a corresponding binary number, which can be compared using eql or used as an index in a list.
Use alexandria:switch from the alexandria library, available from quicklisp.
(switch (combination :test #'string=)
("FOO" …)
…)
Your code just calculates (count #\P combination).
Usually I would convert the string in a number and compute with it. Using LOGCOUNT to get the on bits or something. Even if I were using a large CASE-like switch, I would convert the string once to a number, instead of doing a multitude of string comparisons.
You could write a macro:
(defmacro string-case (key &rest forms)
(let ((k (gensym "KEY")))
`(let ((,k ,key))
(cond
,#(loop for (str . body) in forms
collect `((string= ,k ,str) ,#body))))))
And then use it like case. Note that this macro will check each substring one at a time (up to 32 branches in your case), which is less efficient than eg looking at the first character and deciding what to do, then looking at the next character and so on (5-10 branches in your case), which is less efficient than doing what you actually intend (eg counting #\P) (this can be done with 5-6 easily predicted branches, or maybe 10 depending on implementation). Of these options, the second generated the most code, then the first, then the third.
Another approach would be to convert combination to a symbol. The resulting code will look like this:
(case (intern combination)
(EEEEE 0)
(EEEEP 1)
(EEEPE 1)
...)
But you need to keep in mind that intern operates at runtime in the context of current package (*package*), which means that if this is part of a function that is called outside of the package where it's defined, it will not work. There are 2 ways to work around this (basically, two variations of one): either intern in the package ((intern combination <your-package>)) or intern as keyword. In the later case, the whole form will look like this:
(case (intern combination :keyword)
(:EEEEE 0)
(:EEEEP 1)
(:EEEPE 1)
...)
Also worth noting may be performance considerations. They shouldn't be a problem as, although interning is a rather heavy operation, initially, when it's called repeatedly on an already interned symbol it's, basically, just a dictionary lookup.
Another solution may be to define the rules as a list, and search through the list for the matching string.
(defun match-combination (combination)
(let ((rules '(("EEEEE" 0)
("EEEEP" 1)
("EEEPE" 1)
...)))
(cadr (find combination rules :key #'car :test #'string=))))
Related
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?
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.
I've been trying to write a recursive loop in clojure that will print me out the very last number in the list. The point is not that I need to get the last number (for which I'm sure there's a built in function for that) but that I want to better understand recursion and macros in clojure. So I have this macro...
(defmacro loop-do [the-list]
`(if (= (count '~the-list) 1)
(println (first '~the-list))
(loop-do (rest '~the-list))))
But I get a stackoverflow error. What am I doing wrong?
How will people use your macro?
Somewhere, someone will call:
(loop-do list)
As a piece of code, those are only two symbols in a list. The first one is recognized as your macro, and the second one, list, is a symbol that represents a variable that will be bound at runtime. But your macro only knows that this is a symbol.
The same goes for:
(loop-do (compute-something))
The argument is a form, but you do not want to get the last element of that form, only the last element of the list obtained after evaluating the code.
So: you only know that in your macro, the-list will be bound to an expression that, at runtime, will have to be a list. You cannot use the-list as-if it was a list itself: neither (count 'list) nor (count '(compute-something)) does what you want.
You could expand into (count list) or (count (compute-something)), though, but the result would only be computed at runtime. The job of the macro is only to produce code.
Recursive macros
Macros are not recursive: they expand into recursive calls.
(and a b c)
might expand as:
(let [a0 a] (if a0 a0 (and b c)))
The macroexpansion process is a fixpoint that should terminate, but the macro does not call itself (what would that mean, would you expand the code while defining the macro?). A macro that is "recursive" as-in "expands into recursive invocations" should have a base case where it does not expand into itself (independently of what will, or will not, happen at runtime).
(loop-do x)
... will be replaced by:
(loop-do (rest 'x))
... and that will be expanded again.
That's why the comments say the size actually grows, and that's why you have a stackoverflow error: macroexpansion never finds a fixpoint.
Debugging macros
You have a stackoverflow error. How do you debug that?
Use macroexpand-1, which only performs one pass of macroexpansion:
(macroexpand-1 '(loop-do x))
=> (if (clojure.core/= (clojure.core/count (quote x)) 1)
(clojure.core/println (clojure.core/first (quote x)))
(user/loop-do (clojure.core/rest (quote x))))
You can see that the generated code still contains a call to usr/loop-do , but that the argument is (clojure.core/rest (quote x)). That's the symptom you should be looking for.
Why doesn't the following work?
((if t + -) 1 1)
How can I get the if expression to resolve to provide the correct function? I don't want to repeat myself, as in (if t (+ 1 1) (- 1 1)).
Emacs Lisp is a Lisp-2, meaning it has a separate namespace for functions. To refer to a function as a value in Emacs Lisp, you need to quote it. And to call a function referenced in this way, you need to use funcall. So what you want is:
(funcall (if t '+ '-) 1 1)
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.