I'm looking for a simple way to return a new structure which is a copy of an existing one with some fields changed, without modifying the original.
I get that you can use setf to change the data in one of the fields, like so:
[1]> (defstruct foo bar)
FOO
[1]> (defvar quux (make-foo :bar 12))
QUUX
[1]> (foo-bar quux)
12
[1]> (setf (foo-bar quux) 15)
15
[1]> (foo-bar quux)
15
But as I stated, this essentially destroys the original data, which isn't what I'm going for.
I could of course do something like this:
(defstruct foo bar baz) ; define structure
(defvar quux (make-foo :bar 12 :baz 200)) ; make new instance
(defvar ping (copy-foo quux)) ; copy instance
(setf (foo-bar ping) 15) ; change the bar field in ping
But it seems more like a work-around than anything.
In Erlang you can do something like this:
-record(foo, {bar, baz}). % defines the record
example() ->
Quux = #foo{bar = 12, baz = 200}, % creates an instance of the record
Ping = Quux#foo{bar = 15}. % creates a copy with only bar changed
No data modified.
PS Yes I'm aware that Common Lisp isn't Erlang; but Erlang made it convenient to work with records/structures immutably, and since functional style is encouraged in Common Lisp, it would be nice if there was a similar option available.
Erlang records are similar to Prolog structures. The Prolog I know implements this as a predicate named update_struct/4 which admits a macro expansion: it takes a type parameter and expands into two unifications. The same kind of processing is done in Erlang, according to the documentation. In Common Lisp, we don't need to pass the type explicitly, as shown with the following update-struct function:
(defun update-struct (struct &rest bindings)
(loop
with copy = (copy-structure struct)
for (slot value) on bindings by #'cddr
do (setf (slot-value copy slot) value)
finally (return copy)))
Example
CL-USER> (defstruct foo bar baz)
FOO
CL-USER> (defparameter *first* (make-foo :bar 3))
*FIRST*
CL-USER> (defparameter *second* (update-struct *first* 'baz 2))
*SECOND*
CL-USER> (values *first* *second*)
#S(FOO :BAR 3 :BAZ NIL)
#S(FOO :BAR 3 :BAZ 2)
Specification
Rainer Joswig kindly pointed out that:
There is one thing which is undefined by the standard: using SLOT-VALUE on structure objects is undefined. But it should work on most implementations, as they provide this feature. The only implementation where it does not seem to work is GCL.
Indeed, the HyperSpec says about SLOT-VALUE:
Note in particular that the behavior for conditions and structures is not specified.
An implementation might behave differently if the structured is backed by a list or vector (see the ̀:TYPE option). Anyway, if you need to be portable you'd better use classes.
This topic was also explained in detail by Rainer in common lisp: slot-value for defstruct structures.
Other immutable data-structures
Consider also using property lists, which play nicely with an immutable approach.
Say your initial list x is:
(:a 10 :b 30)
Then (list* :b 0 x) is the following list:
(:b 0 :a 10 :b 30)
... where the most recent value associated with :b shadows the ones after (see GETF).
Loop details
The bindings list is a property list, with alternation of keys and values (like keyword parameters).
In the LOOP expression above, I am iterating over the list of bindings using ON, which means that I am considering each sublist instead of each element. In other words (loop for x on '(a b c d)) successively binds x to (a b c d), (b c d), (c d) and finally (c).
However, since I provide a custom BY argument, the next element is computed using CDDR, instead of the default CDR (so, we advance by two cells instead of by one).
That allows me to consider each pair of key/value elements in the list, and bind them to slot and value thanks to the destructuring syntax.
Related
I am new to common lisp. Is there a CL library to pretty print collections, in my case, nested hash tables?
If you considering writing it yourself, here is a starting point using print-object. It is not implementation independent, but this works at least in LispWorks and SBCL.
(defmethod print-object ((object hash-table) stream)
(format stream "#HASH{~{~{(~a : ~a)~}~^ ~}}"
(loop for key being the hash-keys of object
using (hash-value value)
collect (list key value))))
First, CL does not have a "collection" type.
Second, some (most?) CL implementations will print hash tables with content if you set *print-array* to t.
Third, if your CL implementation does not do that, you can easily whip up your own, based on, say, hash-table->alist.
With the Serapeum library, we can use the dict constructor and enable pretty-printing with (toggle-pretty-print-hash-table):
(dict :a 1 :b 2 :c 3)
;; =>
(dict
:A 1
:B 2
:C 3
)
With the Rutils library:
if we enable pretty printing of hash-tables with (toggle-print-hash-table), they are printed like so:
rutils-user> #h(:foo 42)
#{
:FOO 42
}
It uses print-object under the hood, so its warning applies (not standard, but works in some implementations like SBCL).
The #h reader macro is a shortcut to create hash-tables.
I want to print just the characters from a LISP list, and I need to verify if an atom is not a number, in CLisp. How can I do this?
Here’s how to loop through a list and check for things that aren’t numbers:
(loop for thing in list
do (if (numberp thing)
(format nil “I’m a number: ~a~%” thing)
(format nil “Not a number!~%”)
format is analogous to printf in C. And loop is a macro for iteration in Common Lisp. Explaining how that works beside saying “read the keywords as in English and guess what they mean” is beyond the scope of this answer and there are plenty of explanations of loop online, for example the “Loop for black belts” chapter of Peter Seibel’s Practical Common Lisp with is available free online.
Here is how one can write only the characters in a list. For the sake of variety this one explicitly defines a function and uses higher order list manipulation functions instead of explicit loops. Thus it is probably slower.
(defun print-characters (list)
(let ((chars (remove-if-not #’characterp list)))
(mapc #’write-char chars)))
remove-if-not returns a new list with the same contents as the input except it only includes the elements for which the predicate (in this case characterp) returns true. characterp returns true if and only if its input is a character.
mapc applies a function to each element of a list, discarding the return value. In this case write-char which when called with one argument writes a character to *standard-output*.
I'm assuming you're asking: "given a list of items, how do I filter out only the numbers in the list?"
If yes, here's a sample session:
Given a list:
CL-USER 11 > (setq mylist '(4 "foo" 10 'bar 2.5 "baz"))
(4 "foo" 10 (QUOTE BAR) 2.5 "baz")
To get all the numbers:
CL-USER 13 > (remove-if-not #'numberp mylist)
(4 10 2.5)
And (for completeness) to do the opposite (i.e. remove the numbers):
CL-USER 14 > (remove-if #'numberp mylist)
("foo" (QUOTE BAR) "baz")
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 (...) ...)).
Can someone explain why I get different results for the following simple program with sbcl and clisp? Is what I am doing undefined by the language, or is one of the two lisp interpreters wrong?
; Modify the car of the passed-in list
(defun modify (a) (setf (car a) 123))
; Create a list and print car before and after calling modify
(defun testit () (let ((a '(0)))
(print (car a))
(modify a)
(print (car a))))
(testit)
SBCL (version 1.0.51) produces:
0
0
CLISP (version 2.49) produces (what I would expect):
0
123
I agree with Seth's and Vsevolod's comments in that this behavior is due to your modification of literal data. Try using (list 0) instead of '(0). Questions relating to this come up relatively frequently, so I'll quote the HyperSpec here.
3.7.1 Modification of Literal Objects:
The consequences are undefined if literal objects are destructively
modified.
The definition of "literal":
literal adj. (of an object) referenced directly in a program rather
than being computed by the program; that is, appearing as data in a
quote form, or, if the object is a self-evaluating object, appearing
as unquoted data. ``In the form (cons "one" '("two")), the expressions
"one", ("two"), and "two" are literal objects.''
Note that often (in many implementations), if you modify literal values, you'll really modify them in the code itself – writing self modifying code. Your example code will not work as you expect.
Your example code in CCL:
CL-USER> (defun modify (a) (setf (car a) 123))
MODIFY
CL-USER> (defun testit ()
(let ((a '(0)))
(print (car a))
(modify a)
(print (car a))))
TESTIT
CL-USER> (testit)
0
123
123
CL-USER> (testit)
123
123
123
Take a look at the second evaluation of testit, where the let itself really already contains the modified value, thus the first print also yields 123.
Also see: Lisp, cons and (number . number) difference, where I explained this in more detail, or the question linked in Vsevolod's comment above.
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)