Nested structures in Lisp - struct

I'm starting with Lisp and I need to know if it is possible to use nested structures. Here is my try:
(defstruct casilla i j)
(defstruct tablero caballo reina t1 t2)
(defparameter *estado-inicial*
(make-tablero :caballo (make-casilla :i 1 :j 1)
:reina (make-casilla :i 5 :j 4)
:t1 (make-casilla :i 3 :j 5)
:t2 (make-casilla :i 4 :j 5)))
And if I have to access to the field i:
(defun es-estado-final (estado)
(and (= (caballo-casilla-i estado) 3)
(= (caballo-casilla-j estado) 1)))
Is that right? It seems it isn't because caballo-casilla-i is undefined.
Thanks in advance.

For structs your Lisp environment created for you automatically the accessors tablero-caballo and casilla-i. To combine them you need to use (casilla-i (tablero-caballo estado)). Obviously, you can roll out your own accessor function:
(defun caballo-casilla-i (estado)
(casilla-i (tablero-caballo estado)))
Also you can (declaim (inline caballo-casilla-i)) to not waste additional function calls.

Related

Accessing members of a struct in array Clisp

Imagine I have a function that receive a array of structs like this:
(defun name-of-func (array)
(dotimes (i (array-total-size array))
(print (aref array i))))
and the stuct is something like this
(defstruct sTSP
cidade
x
y)
How can I access the field x on i position of the array?
Please take a look at the definition of defstruct.
It is long, but well worth the read.
If you are lazy, like we all are, search for reader:
(defstruct foo x y z)
(defparameter foo (make-foo :x 2 :y 4))
(foo-x foo)
==> 2
(foo-y foo)
==> 4
(foo-z foo)
==> NIL
PS1. Please note that array-total-size should
not be used with aref but
rather with row-major-aref.
The difference is with multi-dimensional arrays which are implemented
as vectors under the hood.
E.g., your function will fail on (make-array '(2 2) :initial-element (make-sTSP)).
PS2. I re-use foo for both type name and variable name to illustrate that they reside is different name spaces.

Does SBCL for lisp handle scope differently? It does not seem to pass scope into called functions?

When using emacs or my android app I run
(defun big (num) (setf num2 5)(little num)))
(defun little (num)(+ num2 num))
Little happily accepts num2 but when I run it in my SBCL repl (with sublimetext3) it does not.
Is this correct?
What is a workaround without creating a global variable for num2?
I could just pass a second argument (little num num2)
But this wont work when I am trying to mapcar little over a list. Because I can only have one argument when mapcaring correct?
Please read §6. Variables from Practical Common Lisp.
Unlike Emacs Lisp, Common Lisp relies on lexical scope by default (Emacs Lisp is dynamic by default). Dynamic scope (i.e. indefinite scope and dynamic extent) is provided by declaring variables special, and by convention, they are written with asterisks around their names (named "earmuffs"), like *standard-output*. You use defparameter or defvar to declare those variables. Since it has a global effect, you should never use them from inside functions; likewise, your usage of setf is not defined in Common Lisp: no variable named num2 was declared previously in the scope; besides, even if it did, using a global/special variable for local variable is bad style.
Dynamic scope
With special variables, you can for example locally rebind the standard output: the new value is only visible while the code is inside the body of the let binding:
(let ((*standard-output* *error-output*))
(print "Stream redirection"))
By default, print writes to the stream bound to *standard-output*; here, the stream is locally bound to the one given by *error-output*. As soon as you escape the let, *standard-output* reverts to its previous value (imagine there is a stack).
Lexical scope
With lexical scope, your code can only access the bindings that are visible in the text surrounding your code (and the global scope), and the extent is indefinite: it is possible to access a binding (sometimes indirectly) even after the code returns from the let:
(let ((closure
(let ((count 0))
(lambda () (print (incf count))))))
(funcall closure)
(funcall closure))
;; prints:
;; 1
;; 2
The lambda expression creates a closure, which captures the variable named count. Every time you call it, it will increase the count variable and print it. If you evaluate the same code another time, you define another closure and create another variable, with the same name.
Mapcar
Because I can only have one argument when mapcaring correct?
Not exactly; the function called by mapcar should be able to accept at least as many elements as the number of lists that are given to it (and it should also not require more mandatory arguments):
(mapcar (lambda (x y) (* x y))
'(1 2 3)
'(0 3 6))
=> (0 6 18)
(mapcar #'list '(1 2) '(a b) '(+ /))
=> ((1 a +) (2 b /))
The function can also be a closure, and can use special variables.
... with a closure
(defun adder (x)
(lambda (y) (+ x y)))
(mapcar (adder 10) '(0 1 2))
=> (10 11 12)
The adder functions takes a number x and returns a closure which accepts a number y and returns (+ x y).
... with a special variable
If you prefer dynamic scope, use earmuffs and give it a meaningful name:
(defparameter *default-offset* 0)
... and define:
(defun offset (x)
(+ x *default-offset*))
You can then mapcar too:
(let ((*default-offset* 20))
(mapcar #'offset '(1 2 3)))
=> (21 22 23)
As said by jkiiski in comments, you can also declare special variables with (declare (special ...)) where you usually put declarations (when entering a let, a defun, ...). You could also use the special operator progv. This can be useful to have "invisible" variables that are only known by a set of functions to exchange information. You rarely need them.

Split a string even if the last character is a delimiter

I want to delete some characters at the end of a string.
I made this function :
(defun del-delimiter-at-end (string)
(cond
((eq (delimiterp (char string (- (length string) 1))) nil)
string )
(t
(del-delimiterp-at-end (subseq string 0 (- (length string) 1))) ) ) )
with this :
(defun delimiterp (c) (position c " ,.;!?/"))
But I don't understand why it doesn't work. I have the following error :
Index must be positive and not -1
Note that I want to split a string in list of strings, I already looked here :
Lisp - Splitting Input into Separate Strings
but it doesn't work if the end of the string is a delimiter, that's why I'm trying to do that.
What am I doing wrong?
Thanks in advance.
The Easy Way
Just use string-right-trim:
(string-right-trim " ,.;!?/" s)
Your Error
If you pass an empty string to you del-delimiter-at-end, you will be passing -1 as the second argument to char.
Your Code
There is no reason to do (eq (delimiterp ...) nil); just use (delimiterp ...) instead (and switch the clauses!)
It is mode idiomatic to use if and not cond when you have just two clauses and each has just one form.
You call subseq recursively, which means that you not only allocate memory for no reason, your algorithm is also quadratic in string length.
There are really two questions here. One is more specific, and is described in the body of the question. The other is more general, and is what the title asks about (how to split a sequence). I'll handle the immediate question that's in the body, of how to trim some elements from the end of a sequence. Then I'll handle the more general question of how to split a sequence in general, and how to split a list in the special case, since people who find this question based on its title may be interested in that.
Right-trimming a sequence
sds answered this perfectly if you're only concerned with strings. The language already includes string-right-trim, so that's probably the best way to solve this problem, if you're only concerned with strings.
A solution for sequences
That said, if you want a subseq based approach that works with arbitrary sequences, it makes sense to use the other sequence manipulation functions that the language provides. Many functions take a :from-end argument and have -if-not variants that can help. In this case, you can use position-if-not to find the rightmost non-delimiter in your sequence, and then use subseq:
(defun delimiterp (c)
(position c " ,.;!?/"))
(defun right-trim-if (sequence test)
(let ((pos (position-if-not test sequence :from-end t)))
(subseq sequence 0 (if (null pos) 0 (1+ pos)))))
(right-trim-if "hello!" 'delimiterp) ; some delimiters to trim
;=> "hello"
(right-trim-if "hi_there" 'delimiterp) ; nothing to trim, with other stuff
;=> "hi_there"
(right-trim-if "?" 'delimiterp) ; only delimiters
;=> ""
(right-trim-if "" 'delimiterp) ; nothing at all
;=> ""
Using complement and position
Some people may point out that position-if-not is deprecated. If you don't want to use it, you can use complement and position-if to achieve the same effect. (I haven't noticed an actual aversion to the -if-not functions though.) The HyperSpec entry on complement says:
In Common Lisp, functions with names like xxx-if-not are related
to functions with names like xxx-if in that
(xxx-if-not f . arguments) == (xxx-if (complement f) . arguments)
For example,
(find-if-not #'zerop '(0 0 3)) ==
(find-if (complement #'zerop) '(0 0 3)) => 3
Note that since the xxx-if-not functions and the :test-not
arguments have been deprecated, uses of xxx-if functions or :test
arguments with complement are preferred.
That said, position and position-if-not take function designators, which means that you can pass the symbol delimiterp to them, as we did in
(right-trim-if "hello!" 'delimiterp) ; some delimiters to trim
;=> "hello"
complement, though, doesn't want a function designator (i.e., a symbol or function), it actually wants a function object. So you can define right-trim-if as
(defun right-trim-if (sequence test)
(let ((pos (position-if (complement test) sequence :from-end t)))
(subseq sequence 0 (if (null pos) 0 (1+ pos)))))
but you'll have to call it with the function object, not the symbol:
(right-trim-if "hello!" #'delimiterp)
;=> "hello"
(right-trim-if "hello!" 'delimiterp)
; Error
Splitting a sequence
If you're not just trying to right-trim the sequence, then you can implement a split function without too much trouble. The idea is to increment a "start" pointer into the sequence. It first points to the beginning of the sequence. Then you find the first delimiter and grab the subsequence between them. Then find the the next non-delimiter after that, and treat that as the new start point.
(defun split (sequence test)
(do ((start 0)
(results '()))
((null start) (nreverse results))
(let ((p (position-if test sequence :start start)))
(push (subseq sequence start p) results)
(setf start (if (null p)
nil
(position-if-not test sequence :start p))))))
This works on multiple kinds of sequences, and you don't end up with non delimiters in your subsequences:
CL-USER> (split '(1 2 4 5 7) 'evenp)
((1) (5 7))
CL-USER> (split '(1 2 4 5 7) 'oddp)
(NIL (2 4))
CL-USER> (split "abc123def456" 'alpha-char-p)
("" "123" "456")
CL-USER> (split #(1 2 3 foo 4 5 6 let 7 8 list) 'symbolp)
(#(1 2 3) #(4 5 6) #(7 8))
Although this works for sequences of all types, it's not very efficient for lists, since subseq, position, etc., all have to traverse the list up to the start position. For lists, it's better to use a list specific implementation:
(defun split-list (list test)
(do ((results '()))
((endp list)
(nreverse results))
(let* ((tail (member-if test list))
(head (ldiff list tail)))
(push head results)
(setf list (member-if-not test tail)))))
CL-USER> (split-list '(1 2 4 5 7) 'oddp)
(NIL (2 4))
CL-USER> (split-list '(1 2 4 5 7) 'evenp)
((1) (5 7))
Instead of member-if and ldiff, you could also us cut from this answer to Idiomatic way to group a sorted list of integers?.

Haskell-style sections in Common Lisp

In Haskell, if I have a lambda that looks like the following
(\x -> doStuff x y)
where y is from the surrounding scope, I could section it and turn it into
(`doStuff` y)
which is shorter and more concise (and one of the things I love the most about Haskell).
Now, in Common Lisp I would write the equivalent code as
(lambda (x) (do-stuff x y))
And this is actually a very common thing for me to be writing, but I feel even that tiny bit of boilerplate bothers me somewhat, so I wonder if there is a way to get something like the Haskell-style sections in Common Lisp?
Unless you are more experienced, I would propose that you learn to write Lisp in Lisp, not how to write Haskell in Lisp. The latter is not a good idea. Haskell works very different.
Lisp does not do any 'currying' (or schönfinkeling ;-) ).
You can write it as:
CL-USER 5 > (defun curry (fn arg) (lambda (&rest args) (apply fn arg args)))
CURRY
CL-USER 6 > (mapcar (curry #'expt 2) '(2 3 4 5 6))
(4 8 16 32 64)
It costs a bit efficiency that way, though.
CL-USER 7 > (mapcar (lambda (base) (expt base 2)) '(2 3 4 5 6))
(4 8 16 32 64)
I personally prefer the latter, because I have a real readable name for the variable. This helps in a debugger, where I see then a backtrace. Tools like these are probably more important in Lisp, than in Haskell.
CL-USER 12 > (mapcar (lambda (base) (expt base 2)) '(2 3 "four" 5 6))
error. Let's look at the backtrace:
CL-USER 12 : 1 > :bb
...
Condition: In EXPT of ("four" 2) arguments should be of type NUMBER.
Call to SYSTEM::ARGS-TO-BINARY-ARITHMETIC-FN-NOT-OF-TYPE {offset 189}
SYSTEM::FN-NAME : EXPT
SYSTEM::ARG1 : "four"
SYSTEM::ARG2 : 2
TYPE {Closing} : NUMBER
Interpreted call to (SUBFUNCTION :ANONYMOUS SYSTEM::ANONYMOUS-LAMBDA):
BASE : "four"
Now I can see that the thing has a name. I was passing the string "four" to the function with a variable named base.
Interactive development with REPL and debugging tools is common. Best prepare the code to be useful for this development style. Common Lisp is not optimized to provide full program compilers with extensive type checking - like in Haskell.
One of the main problems of Lisp is that it can be very hard to find out what a piece of code really does. The default (strict functional programs with prefix syntax) is relatively easy to understand. But there are many possibilities to change the meaning of code in Lisp (macros, read macros, symbol macros, the Meta Object protocol, advising, ...).
First rule: if you are writing basic Lisp code, stick with the basic syntactic and semantic possibilities. Write defensively. Expect that someone else needs to understand the code. For that the code should be readable, easy to understand, use common idioms and it should be debuggable.
In Haskell many people with math background want to write code in a very compact way with a high level of abstraction. You can do that in Lisp, too. But for ordinary code I would not go that route and for larger pieces of code, Lisp often uses other mechanisms (code transformations via macros, ...).
You can develop arbitrary special syntax for such forms. There're multiple variants. I, for instance, use a Clojure-inspired sharp-backquote syntax. Using it, your form will look like this:
#`(do-stuff % y)
I don't think you can do it directly, but...
If you know that you always want to do something that is equivalent to (lambda (x) (fun x lexical)) and simply want a shorter way of expressing that, you could, in theory, use a macro.
I would, personally, advise against doing so, (lambda (x) (fun x lex)) doesn't take much typing and removes one layer of obscurity from your code. But if it is a pattern that is sufficiently common that it warrants special handling, something like the following might do:
(defmacro section (function lexical)
(let ((sym (gensym))
`(lambda (,sym) (,function ,sym ,lexical))))
That makes the Haskell section:
(`doStuff` y)
become the Common Lisp section:
(section dostuff y)
I don't, as such, find it more readable, at least in the short, but if it was something that I did see again and again, I would indeed consider (and have done, more for experimental purposes than anything else) a macro to make it quicker (I have a half-baked macro, somewhere, that allows you to do things like (_ func _2 lexical _1) -> *(lambda (a b) (func b lexical a)) and that is sometimes handy, but doesn't really improve readability).
There's a sharp backquote read macro in Let Over Lambda that could work for this case:
CL-USER>
(print
'#`,(+ a1 y))
(LAMBDA (A1) (+ A1 Y))
(LAMBDA (A1) (+ A1 Y))
CL-USER>
(let ((y 2))
(mapcar #`,(+ a1 y)
(list 1 2 3 4)))
(3 4 5 6)
CL-USER>
This approach is very similar to the technique mentioned by #Vsevolod Dyomkin. Hoyte's version does have a few extra features, like building a lambda with any number of arguments. On the other hand, it's a bit harder to parse, because it's being expressed at one level higher notation, where in order to eval a form you have to unquote the backquote (using ',' in this example).
Scheme has the cut macro (in SRFI-26), which allows you to specify holes in a procedure call with <>. For example:
(cut doStuff <> y) ;; same as (lambda (x) (doStuff x y))
(cut - 5 <> 6 <> 7) ;; same as (lambda (x y) (- 5 x 6 y 7))
You could probably define something similar in CL.
I also missed the ease of Haskell-style function currying and composition when in common lisp. As a result I wrote the following package which defines reader macros for concise curry and composition in lisp (it uses the alexandria functions).
http://eschulte.github.io/curry-compose-reader-macros/
With this package (mapcar (compose (curry #'* 2) (curry #'+ 1)) (list 1 2 3 4)) becomes (mapcar [{* 2} {+ 1}] (list 1 2 3 4)). I now use this in nearly all of my CL projects and find it greatly reduces code size and increases readability.
The alexandria package exports the symbols curry and rcurry.
So in your case you just do
(alexandria:rcurry function arg) e.g., (rcurry #'do-staff y).
Rcurry and curry return functions so you need to funcall the result as usual.

Is there a generic method for cloning CLOS objects?

I'm looking for a way to clone CLOS objects in a shallow manner, so the created object would be of the same type with the same values in each slot, but a new instance. The closest thing I found is a standard function copy-structure which does this for structures.
There is no standard predefined way to copy CLOS objects in general. It is not trivial, if possible at all, to provide a reasonable default copy operation that does the right thing (at least) most of the time for arbitrary objects, since the correct semantics change from class to class and from application to application. The extended possibilities the MOP provides make it even harder to provide such a default. Also, in CL, being a garbage collected language, copying of objects is not really needed very often, e.g. when passed as parameters or being returned. So, implementing your copy operations as needed would probably be the cleanest solution.
That being said, here is what I found in one of my snippet files, which might do what you want:
(defun shallow-copy-object (original)
(let* ((class (class-of original))
(copy (allocate-instance class)))
(dolist (slot (mapcar #'slot-definition-name (class-slots class)))
(when (slot-boundp original slot)
(setf (slot-value copy slot)
(slot-value original slot))))
copy))
You will need some MOP support for class-slots and slot-definition-name.
(I probably adopted this from an old c.l.l thread, but I can't remember. I never really needed something like this, so it's utterly untested.)
You can use it like this (tested with CCL):
CL-USER> (defclass foo ()
((x :accessor x :initarg :x)
(y :accessor y :initarg :y)))
#<STANDARD-CLASS FOO>
CL-USER> (defmethod print-object ((obj foo) stream)
(print-unreadable-object (obj stream :identity t :type t)
(format stream ":x ~a :y ~a" (x obj) (y obj))))
#<STANDARD-METHOD PRINT-OBJECT (FOO T)>
CL-USER> (defparameter *f* (make-instance 'foo :x 1 :y 2))
*F*
CL-USER> *f*
#<FOO :x 1 :y 2 #xC7E5156>
CL-USER> (shallow-copy-object *f*)
#<FOO :x 1 :y 2 #xC850306>
Here's a slightly different version of the function submitted by danlei. I wrote this a while ago and just stumbled across this post. For reasons that I don't entirely recall, this calls REINITIALIZE-INSTANCE after copying. I think it's so you could make some changes to the new object by passing additional initargs to this function
e.g.
(copy-instance *my-account* :balance 100.23)
This is also defined as generic function over objects that are 'standard-object's. Which might or might not be the right thing to do.
(defgeneric copy-instance (object &rest initargs &key &allow-other-keys)
(:documentation "Makes and returns a shallow copy of OBJECT.
An uninitialized object of the same class as OBJECT is allocated by
calling ALLOCATE-INSTANCE. For all slots returned by
CLASS-SLOTS, the returned object has the
same slot values and slot-unbound status as OBJECT.
REINITIALIZE-INSTANCE is called to update the copy with INITARGS.")
(:method ((object standard-object) &rest initargs &key &allow-other-keys)
(let* ((class (class-of object))
(copy (allocate-instance class)))
(dolist (slot-name (mapcar #'sb-mop:slot-definition-name (sb-mop:class-slots class)))
(when (slot-boundp object slot-name)
(setf (slot-value copy slot-name)
(slot-value object slot-name))))
(apply #'reinitialize-instance copy initargs))))
This solution does not require sl-mob:
(defun copy-slot (s d slot)
`(setf (,slot ,d) (,slot ,s)))
(defun copy-by-slots (s d slots)
(assert (eql (class-of s) (class-of d)))
(let ((f (lambda (s$) (eval (copy-slot s d s$)))))
(mapcar f slots)))
(copy-by-slots src dest quoted-list-of-slots)
I mention a dirty trick producing a clone of a CLOS instance.
(defclass cl () ((sl1 :initarg :sl1) (sl2 :initarg :sl2)))
(defmethod update-instance-for-different-class ((copy cl) (original cl) &key)
(setf clone copy))
(setf a (make-instance 'cl :sl1 111 :sl2 222))
(change-class a 'cl)
(eq clone a) -> NIL
(eql (slot-value a 'sl1) (slot-value clone 'sl1)) -> T
Implies CLOS itself needs a notion of clone.

Resources