common lisp: slot-value for defstruct structures - common-lisp

In common lisp, what can I use to access structure slot using slot name/symbol?
What I want is
(defstruct point (x 0) (y 0))
(defmacro -> (struct slot) `(slot-value ,struct ,slot))
(setf p (make-point))
(setf (slot-value p 'x) 1)
(setf (-> p 'y) 2)
I'm using clozure cl, and In clozure cl this works. However, AFAIK this is non-standard behavior (equivalent to "undefined behavior" C++). I'm not planning to switch to another CL implementation, so should I keep using slot-value for structures, or is there a better way to do it?

Usually you would use accessor functions with structures.
Your code defines the accessor functions point-x and point-y. You can use those.
You can also use SLOT-VALUE with structures on implementations which support it. I guess that's most implementations (GCL would be an exception). There is Lisp software which assumes that SLOT-VALUE works for structures. I don't think implementations will remove support for it. It'a not in the standard, because some implementors wouldn't want to provide this functionality in deployed applications.
So both ways are okay.
If you want to have short names, go with accessors:
CL-USER 109 > (defstruct (point :conc-name)
(x 0) (y 0))
POINT
CL-USER 110 > (make-point :x 5 :y 3)
#S(POINT :X 5 :Y 3)
CL-USER 111 > (setf p1 *)
#S(POINT :X 5 :Y 3)
CL-USER 112 > (x p1)
5
CL-USER 113 > (setf p2 (make-point :x 2 :y 3))
#S(POINT :X 2 :Y 3)
CL-USER 114 > (list p1 p2)
(#S(POINT :X 5 :Y 3) #S(POINT :X 2 :Y 3))
CL-USER 115 > (mapcar 'x (list p1 p2))
(5 2)
Name clashes between various accessor functions then would have to be prevented by a package.
If you want to write a shorter version of SLOT-VALUE, that's also fine. Write a macro. Or write an inlined function. Sure - why not?
As I said, SLOT-VALUE works with structures in most implementations. In this case you should not care that the ANSI CL spec does not define that. In many ways implementations extend the ANSI CL spec. For example by SLOT-VALUE working on structures, implementing streams as CLOS classes, implementing conditions as CLOS classes, providing a Meta-object Protocol, ...

Related

Computing linear combination of vectors in Common Lisp

I'm working on some numerical computations in Common Lisp and I need to compute a linear combination of several vectors with given numerical coefficients. I'm rewriting a piece of Fortran code, where this can be accomplished by res = a1*vec1 + a2*vec2 + ... + an*vecn. My initial take in CL was to simply write each time something like:
(map 'vector
(lambda (x1 x2 ... xn)
(+ (* x1 a1) (* x2 a2) ... (* xn an)))
vec1 vec2 ... vecn)
But I soon noticed that this pattern would recur over and over again, and so started writing some code to abstract it away. Because the number of vectors and hence the number of lambda's arguments would vary from place to place, I figured a macro would be required. I came up with the following:
(defmacro vec-lin-com (coefficients vectors &key (type 'vector))
(let ((args (loop for v in vectors collect (gensym))))
`(map ',type
(lambda ,args
(+ ,#(mapcar #'(lambda (c a) (list '* c a)) coefficients args)))
,#vectors)))
Macroexpanding the expression:
(vec-lin-com (10 100 1000) (#(1 2 3) #(4 5 6) #(7 8 9)))
yields the seemingly correct expansion:
(MAP 'VECTOR
(LAMBDA (#:G720 #:G721 #:G722)
(+ (* 10 #:G720) (* 100 #:G721) (* 1000 #:G722)))
#(1 2 3) #(4 5 6) #(7 8 9))
So far, so good...
Now, when I try to use it inside a function like this:
(defun vector-linear-combination (coefficients vectors &key (type 'vector))
(vec-lin-com coefficients vectors :type type))
I get a compilation error stating essentially that The value VECTORS is not of type LIST. I'm not sure how to approach this. I feel I'm missing something obvious. Any help will be greatly appreciated.
You've gone into the literal trap. Macros are syntax rewriting so when you pass 3 literal vectors in a syntax list you can iterate on them at compile time, but replacing it with a bindnig to a list is not the same. The macro only gets to see the code and it doesn't know what vectors will eventually be bound to at runtime when it does its thing. You should perhaps make it a function instead:
(defun vec-lin-com (coefficients vectors &key (type 'vector))
(apply #'map
type
(lambda (&rest values)
(loop :for coefficient :in coefficients
:for value :in values
:sum (* coefficient value)))
vectors))
Now you initial test won't work since you passed syntax and not lists. you need to quote literals:
(vec-lin-com '(10 100 1000) '(#(1 2 3) #(4 5 6) #(7 8 9)))
; ==> #(7410 8520 9630)
(defparameter *coefficients* '(10 100 1000))
(defparameter *test* '(#(1 2 3) #(4 5 6) #(7 8 9)))
(vec-lin-com *coefficients* *test*)
; ==> #(7410 8520 9630)
Now you could make this a macro, but most of the job would have been done by the expansion and not the macro so basically you macro would expand to similar code to what my function is doing.
Remember that macros are expanded at compile-time, so the expression ,#(mapcar #'(lambda (c a) (list '* c a)) coefficients args) has to be meaningful at compile-time. In this case, all that mapcar gets for coefficients and args are the symbols coefficients and vectors from the source code.
If you want to be able to call vec-lin-com with an unknown set of arguments (unknown at compile-time, that is), you'll want to define it as a function. It sounds like the main problem you're having is getting the arguments to + correctly ordered. There's a trick using apply and map to transpose a matrix that may help.
(defun vec-lin-com (coefficients vectors)
(labels
((scale-vector (scalar vector)
(map 'vector #'(lambda (elt) (* scalar elt)) vector))
(add-vectors (vectors)
(apply #'map 'vector #'+ vectors)))
(let ((scaled-vectors (mapcar #'scale-vector coefficients vectors)))
(add-vectors scaled-vectors))))
This isn't the most efficient code in the world; it does a lot of unnecessary consing. But it is effective, and if you find this to be a bottleneck you can write more efficient versions, including some that can take advantage of compile-time constants.

Memoization with a closure example from Land of Lisp

On page 329 of Land of Lisp, Conrad Barski explains the technique of memoization with the following example code
(let ((old-neighbors (symbol-function 'neighbors))
(previous (make-hash-table)))
(defun neighbors (pos)
(or (gethash pos previous)
(setf (gethash pos previous) (funcall old-neighbors pos)))))
The idea is nice: when I call the neighbors function, I save the result into a hash table, so that the next time calling neighbors with the same value of pos, I can just look-up the result without having to compute it again.
So I was wondering, whether it would not be easier to rename the function neighbors to old-neighbors by editing and recompiling its source code (given on page 314 of the book). Then the memoization example could be simplified to
(let ((previous (make-hash-table)))
(defun neighbors (pos)
(or (gethash pos previous)
(setf (gethash pos previous) (funcall old-neighbors pos)))))
or, by turning previous into a global variable *previous-neighbors* beforehand, even into
(defun neighbors (pos)
(or (gethash pos *previous-neighbors*)
(setf (gethash pos *previous-neighbors*) (funcall old-neighbors pos))))
thus rendering the closure unnecessary.
So my question is: what is the reason for doing it this way?
Reasons I could imagine:
It's didactical, showing what could be done with a closure (which had been explained just before) and providing an example of symbol-function.
This technique is applicable even in situations, where you cannot or may not change the source code of neighbors.
I am missing something.
You have made some good observations.
Generally the style to use closures like that is more likely to be found in Scheme code - where Scheme developers often use functions to return functions.
Generally as you have detected it makes little sense to have a memoize function foo calling an function old-foo. Using global variables reduces encapsulation (-> information hiding), but increases the ability to debug a program, since one can more easily inspect the memoized values.
A similar, but potentially more useful, pattern would be this:
(defun foo (bar)
<does some expensive computation>)
(memoize 'foo)
Where ˋmemoizeˋ would be something like this
(defun memoize (symbol)
(let ((original-function (symbol-function symbol))
(values (make-hash-table)))
(setf (symbol-function symbol)
(lambda (arg &rest args)
(or (gethash arg values)
(setf (gethash arg values)
(apply original-function arg args)))))))
The advantage is that you don't need to write the memoizing code for each function. You only need one function memoize. In this case the closure also makes sense - though you could also have a global table storing memoize tables.
Note the limitations of above: the comparison uses EQL and only the first argument of the function to memoize.
There are also more extensive tools to provide similar functionality.
See for example:
https://github.com/fare/fare-memoization
https://github.com/sharplispers/cormanlisp/blob/master/examples/memoize.lisp
https://github.com/AccelerationNet/function-cache
Using my memoize from above:
CL-USER 22 > (defun foo (n)
(sleep 3)
(expt 2 n))
FOO
CL-USER 23 > (memoize 'foo)
#<Closure 1 subfunction of MEMOIZE 40600008EC>
The first call with arg 10 runs three seconds:
CL-USER 24 > (foo 10)
1024
The second call with arg 10 runs faster:
CL-USER 25 > (foo 10)
1024
The first call with arg 2 runs three seconds:
CL-USER 26 > (foo 2)
4
The second call with arg 2 runs faster:
CL-USER 27 > (foo 2)
4
The third call with arg 10 runs fast:
CL-USER 28 > (foo 10)
1024

ignore-error on Common Lisp

I'm trying to handle errors in Common Lisp easily, but I have some problems.
In particular, I have this function.
(defun function1 (m)
(ignore-errors (and (condition-1) (condition-2))
(format t "Error message")))
I just want that if some conditions fail into the
(and (condition-1) (condition-2))
it's shown the error message, otherwise just
T
How can I do?
There is a better way to handle this type of errors? I looking for something very simple.
Someone can do an example showing how to use ignore-error?
Thank you.
You can use HANDLER-CASE
CL-USER 101 > (handler-case (and (evenp 2)
(oddp 1))
(error (c)
(princ c)
(values)))
T
CL-USER 102 > (handler-case (and (evenp 2)
(/ 3 0)
(oddp 1))
(error (c)
(princ c)
(values)))
Division-by-zero caused by / of (3 0).

Does macrolet prohibit recursive calls among locally defined macros?

In his book ANSI Common Lisp, p.320, Paul Graham writes of macrolet: "Like flet, the local macros may not call one another."
Maybe I misunderstand this but I can't think of any way in which it could be true. Macros do not call each other so much as expand into each other and the nature of macro expansion is such that it continues until all macros defined in the scope have been expanded away.
Code such as the following disagrees with Graham in every implentation of Common Lisp I've tried:
(macrolet ((jump (x) `(car ,x))
(skip (x) `(jump ,x))
(hop (x) `(skip ,x)))
(hop '(1 2 3)))
=> 1
(macrolet ((yin (n x)
(if (zerop n)
`(cdr ,x)
`(yang ,(1- n) ,x)))
(yang (n x)
(if (zerop n)
`(car ,x)
`(yin ,(1- n) ,x))))
(yin 6 '(1 2 3)))
=> (2 3)
Is Graham's statement in error?
It is okay for a macro defined by macrolet to expand into the use of a different macro defined in the same macrolet. It is incorrect for a macro defined by macrolet to directly use a different macro defined in the same macrolet. For example:
(macrolet ((jump (x) `(car ,x))
;; Okay since skip expands into jump.
(skip (x) `(jump ,x)))
(skip '(1 2 3)))
=> 1
as opposed to
(macrolet ((jump (x) `(car ,x))
;; Wrong since skip uses jump directly.
(skip (x) (jump x)))
(skip '(1 2 3)))
=> Error: The function COMMON-LISP-USER::JUMP is undefined.

List operations in Lisp

I have been searching everywhere for the following functionality in Lisp, and have gotten nowhere:
find the index of something in a list. example:
(index-of item InThisList)
replace something at a specific spot in a list. example:
(replace item InThisList AtThisIndex) ;i think this can be done with 'setf'?
return an item at a specific index. example:
(return InThisList ItemAtThisIndex)
Up until this point, I've been faking it with my own functions. I'm wondering if I'm just creating more work for myself.
This is how I've been faking number 1:
(defun my-index (findMe mylist)
(let ((counter 0) (found 1))
(dolist (item mylist)
(cond
((eq item findMe) ;this works because 'eq' checks place in memory,
;and as long as 'findMe' was from the original list, this will work.
(setq found nil)
(found (incf counter))))
counter))
You can use setf and nth to replace and retrieve values by index.
(let ((myList '(1 2 3 4 5 6)))
(setf (nth 4 myList) 101); <----
myList)
(1 2 3 4 101 6)
To find by index you can use the position function.
(let ((myList '(1 2 3 4 5 6)))
(setf (nth 4 myList) 101)
(list myList (position 101 myList)))
((1 2 3 4 101 6) 4)
I found these all in this index of functions.
find the index of something in a list.
In Emacs Lisp and Common Lisp, you have the position function:
> (setq numbers (list 1 2 3 4))
(1 2 3 4)
> (position 3 numbers)
2
In Scheme, here's a tail recursive implementation from DrScheme's doc:
(define list-position
(lambda (o l)
(let loop ((i 0) (l l))
(if (null? l) #f
(if (eqv? (car l) o) i
(loop (+ i 1) (cdr l)))))))
----------------------------------------------------
> (define numbers (list 1 2 3 4))
> (list-position 3 numbers)
2
>
But if you're using a list as a collection of slots to store structured data, maybe you should have a look at defstruct or even some kind of Lisp Object System like CLOS.
If you're learning Lisp, make sure you have a look at Practical Common Lisp and / or The Little Schemer.
Cheers!
Answers:
(position item sequence &key from-end (start 0) end key test test-not)
http://lispdoc.com/?q=position&search=Basic+search
(setf (elt sequence index) value)
(elt sequence index)
http://lispdoc.com/?q=elt&search=Basic+search
NOTE: elt is preferable to nth because elt works on any sequence, not just lists
Jeremy's answers should work; but that said, if you find yourself writing code like
(setf (nth i my-list) new-elt)
you're probably using the wrong datastructure. Lists are simply linked lists, so they're O(N) to access by index. You might be better off using arrays.
Or maybe you're using lists as tuples. In that case, they should be fine. But you probably want to name accessors so someone reading your code doesn't have to remember what "nth 4" is supposed to mean. Something like
(defun my-attr (list)
(nth 4 list))
(defun (setf my-attr) (new list)
(setf (nth 4 list) new))
+2 for "Practical Common Lisp". It is a mixture of a Common Lisp Cookbook and a quality Teach Yourself Lisp book.
There's also "Successful Common Lisp" (http://www.psg.com/~dlamkins/sl/cover.html and http://www.psg.com/~dlamkins/sl/contents.html) which seemed to fill a few gaps / extend things in "Practical Common Lisp".
I've also read Paul Graham's "ANSI Common Lisp" which is more about the basics of the language, but a bit more of a reference manual.
I have to agree with Thomas. If you use lists like arrays then that's just going to be slow (and possibly awkward). So you should either use arrays or stick with the functions you've written but move them "up" in a way so that you can easily replace the slow lists with arrays later.

Resources