Change an editable-text value in Allegro CL - lisp

I'm trying to change the value of an Editable-Text control in Allegro CL (version 8.0.1) by clicking a Default-Button.
I've read about (setf value) but haven't found any examples.
The function I have ttached to the on-click event is the following
(defun form1-default-button-2-on-click (dialog widget)
(declare (ignorable dialog widget))
t)
As you can see there's a lack of code in there :) I've tried various methods as (setf (slot value :txt 'value) 'TEXT) and (setf value 'TEXT) but to no avail.
The dialog-items slot on the form is a list with the following elements defined by
(list (make-instance 'default-button :font
(make-font-ex nil "Segoe UI / Default" 12) :left
56 :name :default-button-2 :on-change
'form1-default-button-2-on-change :top 36)
(make-instance 'editable-text :font
(make-font-ex nil "Segoe UI / Default" 12) :left
52 :name :txt :top 152 :value "")
)
Any help? Thanks in advance.

(setf (slot-value widget 'value) "foo")
Something like the above. You need get the symbol value in the correct package. probably there is also an accessor function like WIDGET-VALUE . Then (setf (widget-value widget) "foo") might work...
I'm not an ACL user - there are probably better ways. ACL specific questions are best asked on their users mailing list.

There is an example somewhere on franz.com where I found this:
(defun form1-button5-on-change (widget new-value old-value)
(declare (ignorable widget new-value old-value))
(let ((szerkeszto (find-sibling :multi-line-editable-text-1 widget)))
(setf (value szerkeszto) "bla" ))
t) ; Accept the new value
symbol "szerkeszto" becomes the multi-line-editable-text-1, then you can use setf like the above to set appropriate attributes (like "value").
hope this helps.

You need to use the functions "find-component" and "value" together.
The function "find-component" finds the widget in your project
and "value" returns the value of the widget.
If you have static-text in a form, you can change the value of the static-text like this.
(let ((ed1 (find-component :static-text-1 :form1)))
(setf (value ed1) "I made it."))

Related

Advanced symbol-macrolet

Suppose I have a class class with slots first and second. Inside my function I can bind a variable to one of those slots like
(symbol-macrolet ((var (first cls)))
....)
Obviously I can also bind the second slot to smth.
Questions is, let's say that first and second are either some number or nil. Let's also say that if second is non-nil, first is always nil. Now, can I bind my var to a non-nil one with just one macro? So it just looks at instance of the class given and then check if second is nil. If no, it binds var to second, otherwise to first.
Seems complicated, but I'm pretty sure it can be done, just don't know where to start.
To further generalize -- is it possible to bond a variable not to a single place, but to one of a specific set, depending on some state?
I think this is not quite simple. You could do something like this which works for reading only (I've used a fake toy structure so my code works, which is given here):
(defstruct toy
(first nil)
(second nil))
(defun foo (a-toy)
(symbol-macrolet ((x (or (toy-first a-toy) (toy-second a-toy))))
...))
But now (setf x ...) is horribly illegal. You can get around this, once you've decided what (setf x ...) should do, by defining some local functions. I've decided here that it should set the non-nil slot, as that makes sense to me.
(defun bar (a-toy)
(flet ((toy-slot (the-toy)
(or (toy-first the-toy) (toy-second the-toy)))
((setf toy-slot) (new the-toy)
(if (toy-first the-toy)
(setf (toy-first the-toy) new)
(setf (toy-second the-toy) new))))
(symbol-macrolet ((x (toy-slot a-toy)))
(setf x 2)
a-toy)))
And now you can wrap this all in a single macro:
(defmacro binding-toy-slot ((x toy) &body forms)
(let ((tsn (make-symbol "TOY-SLOT")))
`(flet ((,tsn (the-toy)
(or (toy-first the-toy) (toy-second the-toy)))
((setf ,tsn) (new the-toy)
(if (toy-first the-toy)
(setf (toy-first the-toy) new)
(setf (toy-second the-toy) new))))
(symbol-macrolet ((,x (,tsn ,toy)))
,#forms))))
(defun bar (a-toy)
(binding-toy-slot (x a-toy)
(setf x 3)
a-toy))
Obviously you might want to generalise binding-toy-slot, so it, for instance, takes a list of slot accessor names or something like that.
There may also be better ways of doing this I haven't thought of: there might be clever tricks with setf-expansions that let you do it without the little helper functions. You could also have global helper functions which get passed an object and a list of accessors to try which would make the code slightly smaller (although you can probably achieve similarly small code in any serious implementation by declaring the helpers inline which should cause them to be completely compiled away).
An alternative, and perhaps better, approach, is to define the protocol you want to achieve using generic functions. This means things are defined globally, and it's related to but not quite the same as Kaz's answer.
So again, let's say I have some class (this can be a structure, but making it a fully-fledged standard-class lets us have unbound slots, which is nice):
(defclass toy ()
((first :initarg :first)
(second :initarg :second)))
Now you could either define generic functions with names like appropriate-slot-value & (setf appropriate-slot-value), or you could define GF which returns the name of the appropriate slot, like so:
(define-condition no-appropriate-slot (unbound-slot)
;; this is not the right place in the condition heirarchy probably
()
(:report "no appropriate slot was bound"))
(defgeneric appropriate-slot-name (object &key for)
(:method :around (object &key (for ':read))
(call-next-method object :for for)))
(defmethod appropriate-slot-name ((object toy) &key for)
(let ((found (find-if (lambda (slot)
(slot-boundp object slot))
'(first second))))
(ecase for
((:read)
(unless found
(error 'no-appropriate-slot :name '(first second) :instance object))
found)
((:write)
(or found 'first)))))
And now the accessor function pair can be plain functions which will work for any class where there is a method for appropriate-slot-name:
(defun appropriate-slot-value (object)
(slot-value object (appropriate-slot-name object :for ':read)))
(defun (setf appropriate-slot-value) (new object)
;; set the bound slot, or the first slot
(setf (slot-value object (appropriate-slot-name object :for ':write)) new))
Finally, we can now have functions which just use symbol-macrolet in the obvious way:
(defun foo (something)
(symbol-macrolet ((s (appropriate-slot-value something)))
... s ... (setf s ...) ...))
So, that's another approach.
Simple, inefficient way with defsetf:
(defun second-or-first (list)
(or (second list) (first list)))
(defun set-second-or-first (list val)
(if (second list)
(setf (second list) val)
(setf (first list) val)))
(defsetf second-or-first set-second-or-first)
(defun test ()
(let ((list (list nil nil)))
(symbol-macrolet ((sof (second-or-first list)))
(flet ((prn ()
(prin1 list) (terpri)
(prin1 sof) (terpri)))
(prn)
(setf sof 0)
(prn)
(setf sof 1)
(prn)
(setf (second list) 3)
(prn)
(setf sof nil)
(prn)
(setf sof nil)
(prn)))))
If it is okay that update expressions like (incf sof) wastefully traverse the structure twice, this is adequate.
Otherwise a more sophisticated implementation is required using define-setf-expander. The gist of such a solution is that the generated code has to calculate which of the two cons cells of the list holds the current place, storing that cons cell in a temporary variable #:temp. Then the place we are interested in is denoted by (car #:temp). If #:temp is the second cell, avoiding two accesses to are tricky (one access to determine it's the one we want, then the other to get the prior value). Basically what we can do is have another temp variable which holds the value of the place that we obtained as a side effect of checking whether it is not nil. Then designate that temporary variable as the access form for getting the prior value.
Here’s how you might not use symbol macros without any huge loss:
(defgeneric firsty-secondy (thing))
(defgeneric (setf firsty-secondy) (newval thing))
(defmethod firsty-secondy ((x my-class))
(or (secondy x) (firsty x)))
(defmethod (setf firsty-secondy) (nv (x my-class))
(if (secondy x)
(setf (secondy x) nv)
(setf (firsty x) nv)))
You may find that the compiler does better with these because within the methods it can be more sure about where the slots for the fields are in memory.
Here is a way to structure your object to not need to do this and enforce your invariant a bit better:
(defclass my-class
((is-first :initform nil)
(thingy :initform nil)))
Here is a comparison:
first=nil,second=nil : is-first=nil,thingy=nil
first=123,second=nil : is-first=t ,thingy=123
first=nil,second=123 : is-first=nil,thingy=123
first=123,second=456 : unrepresentable

How do I write a macro that will repeat a command?

I'm trying to write a macro that will let me streamline the definition of multiple top-level variables in one single expression.
The idea was to make it work similar to how let works:
(defparameters ((*foo* 42)
(*bar* 31)
(*baz* 99)))
I tried using the following, but it doesn't seem to do anything.
(defmacro defparameters (exprs)
(dolist (expr exprs)
(let ((name (car expr))
(exp (cadr expr)))
`(defparameter ,name ,exp))))
I've tried using macroexpand but it doesn't seem to expand at all.
What am I doing wrong? and how can I fix it?
The return value of a dolist is given by its optional third argument, so your macro returns the default of nil.
Macros only return one form, so when you have multiple things, such as your series of defparameters, you need to wrap them all in some form and return that. progn will be suitable here. For Example:
(defmacro defparameters (exprs)
`(progn ,#(loop for (name exp) in exprs
collect `(defparameter ,name ,exp))))

combining two variables into one function name in macro

I was toying around with macros and clos, where I created an "object" macro to create instances
(defmacro object (class &rest args)
`(make-instance ',class ,#args))
Now doing this, I also ended up kind of wanting to do something similar for accessor functions created by clos. Example:
(defclass person () ((name :accessor person-name :initarg :name)))
then creating the instance
(setf p1 (object person :name "tom"))
now to get the name from the object obviously I would call person-name, however just as with the object macro, I wanted to create a "gets" macro to do this. So ideally:
(gets person name p1) which then would return the name.
The problem then is the binding of person and name (person-name) and how to do that. Is there anyway to get those two arguments bound together in the macro? sort of like:
(defmacro gets (class var object)
`(,class-,var ,object))
I think I may have misunderstood the original intent. At first I thought you were asking how to generate the accessor names for the class definition, which third part of the answer addresses. After reading through a second time, it actually sounds like you want to generate a new symbol and call it with some argument. That's easy enough too, and is given in the second part of this answer. Both the second and third parts depend on being able to create a symbol with a name that's built from the names of other symbols, and that's what we start with.
"Concatenating" symbols
Each symbol has a name (a string) that you can obtain with symbol-name. You can use concatenate to create a new string from some old strings, and then use intern to get a symbol with the new name.
(intern (concatenate 'string
(symbol-name 'person)
"-"
(symbol-name 'name)))
;=> PERSON-NAME
Reconstructing an accessor name
(defmacro gets (class-name slot-name object)
(let ((accessor-name
(intern (concatenate 'string
(symbol-name class-name)
"-"
(symbol-name slot-name))
(symbol-package class-name))))
`(,accessor-name ,object)))
(macroexpand-1 '(gets person name some-person))
;=> (PERSON-NAME SOME-PERSON)
For a number of reasons, though, this isn't very robust. (i) You don't know whether or not the slot has an accessor of the form <class-name>-<slot-name>. (ii) Even if the slot does have an accessor of the form <class-name>-<slot-name>, you don't know what package it's in. In the code above, I made the reasonable assumption that it's the same as the package of the class name, but that's not at all required. You could have, for instance:
(defclass a:person ()
((b:name :accessor c:person-name)))
and then this approach wouldn't work at all. (iii) This doesn't work with inheritance very well. If you subclass person, say with north-american-person, then you can still call person-name with a north-american-person, but you can't call north-american-person-name with anything. (iv) This seems to be reïnventing slot-value. You can already access the value of a slot using the name of the slot alone with (slot-value object slot-name), and I don't see any reason that your gets macro shouldn't just expand to that. There you wouldn't have to worry about the particular name of the accessor (if it even has one), or the package of the class name, but just the actual name of the slot.
Generating accessor names
You just need to extract the names of the symbols and to generate a new symbol with the desired name.
If you want to automatically generate accessors with defstruct style names, you can do it like this:
(defmacro define-class (name direct-superclasses slots &rest options)
(flet ((%slot (slot)
(destructuring-bind (slot-name &rest options)
(if (listp slot) slot (list slot))
`(,slot-name ,#options :accessor ,(intern (concatenate 'string
(symbol-name name)
"-"
(symbol-name slot-name)))))))
`(defclass ,name ,direct-superclasses
,(mapcar #'%slot slots)
,#options)))
You can check that this produces the kind of code that you'd expect by looking at the macroexpansion:
(pprint (macroexpand-1 '(define-class person ()
((name :type string :initarg :name)
(age :type integer :initarg :age)
home))))
(DEFCLASS PERSON NIL
((NAME :TYPE STRING :INITARG :NAME :ACCESSOR PERSON-NAME)
(AGE :TYPE INTEGER :INITARG :AGE :ACCESSOR PERSON-AGE)
(HOME :ACCESSOR PERSON-HOME)))
And we can see that it works as expected:
(define-class person ()
((name :type string :initarg :name)
(age :type integer :initarg :age)
home))
(person-name (make-instance 'person :name "John"))
;=> "John"
Other comments on your code
(defmacro object (class &rest args)
`(make-instance ',class ,#args))
As Rainer pointed out this isn't very useful. For most cases, it's the same as
(defun object (class &rest args)
(apply 'make-instance class args))
except that you can (funcall #'object …) and (apply #'object …) with the function, but you can't with the macro.
Your gets macro isn't really any more useful than slot-value, which takes an object and the name of a slot. It doesn't require the name of the class, and it will work even if the class doesn't have a reader or accessor.
Don't (naïvely) create symbol names with format
I've been creating symbol names with concatenate and symbol-name. Sometimes you'll see people use format to construct the names, e.g., (format nil "~A-~A" 'person 'name), but that's prone to issues with capitalization settings that can be changed. For instance, in the following, we define a function foo-bar, and note that the format based approach fails, but the concatenate based approach works.
CL-USER> (defun foo-bar ()
(print 'hello))
FOO-BAR
CL-USER> (foo-bar)
HELLO
HELLO
CL-USER> (setf *print-case* :capitalize)
:Capitalize
CL-USER> (funcall (intern (concatenate 'string (symbol-name 'foo) "-" (symbol-name 'bar))))
Hello
Hello
CL-USER> (format nil "~a-~a" 'foo 'bar)
"Foo-Bar"
CL-USER> (intern (format nil "~a-~a" 'foo 'bar))
|Foo-Bar|
Nil
CL-USER> (funcall (intern (format nil "~a-~a" 'foo 'bar)))
; Evaluation aborted on #<Undefined-Function Foo-Bar {1002BF8AF1}>.
The issue here is that we're not preserving the case of the symbol names of the arguments. To preserve the case, we need to explicitly extract the symbol names, rather than letting the print functions map the symbol name to some other string. To illustrate the problem, consider:
CL-USER> (setf (readtable-case *readtable*) :preserve)
PRESERVE
;; The symbol-names of foo and bar are "foo" and "bar", but
;; you're upcasing them, so you end up with the name "FOO-BAR".
CL-USER> (FORMAT NIL "~{~A~^-~}" (MAPCAR 'STRING-UPCASE '(foo bar)))
"FOO-BAR"
;; If you just concatenate their symbol-names, though, you
;; end up with "foo-bar".
CL-USER> (CONCATENATE 'STRING (SYMBOL-NAME 'foo) "-" (SYMBOL-NAME 'bar))
"foo-bar"
;; You can map symbol-name instead of string-upcase, though, and
;; then you'll get the desired result, "foo-bar"
CL-USER> (FORMAT NIL "~{~A~^-~}" (MAPCAR 'SYMBOL-NAME '(foo bar)))
"foo-bar"
This function creates symbols from string designators:
(defun symb (&rest args)
(intern (format nil "~{~a~^-~}" (mapcar #'string args))))
The function uses format, yet passes Joshua's test:
CL-USER> (symb 'foo :bar "BAZ")
FOO-BAR-BAZ
NIL
CL-USER> (defun foo-bar ()
(print 'hello))
FOO-BAR
CL-USER> (foo-bar)
HELLO
HELLO
CL-USER> (setf *print-case* :capitalize)
:Capitalize
CL-USER> (funcall (symb 'foo 'bar))
Hello
Hello
If you want your gets to use accessor methods:
(defmacro gets (class var object)
`(,(intern (format nil "~a-~a" (symbol-name class) (symbol-name var))) ,object))
In general, what you're trying to accomplish is not really useful. make-instance is a well known symbol, easily greppable, part of the standard and optimized by some implementations when the class name is constant. So with your object macro, you're just saving a few characters and a single-quote. Usually, one hides make-instance in specific cases where you don't want to provide a direct way to initialize instances, or more likely, when you want to provide layers of initialization (e.g. phases of initialization, Lisp slots and foreign objects).
PS: I remember vaguely that someone prominent in the standardization of Common Lisp argued in favor of always wrapping/hiding make-instance in a function (e.g. make-<class-name>), but I can't find either a reference or the reasoning.
PPS: Here's a rather old discussion (2004) about it in comp.lang.lisp (and another one from 2002). The main reasons people cite in favor of constructor functions are:
Required arguments; achievable at runtime instead of at compile-time with :initform (error ...) in a slot that requires a provided initial value
Generally, hide implementation details: class instance, structure instance, cons, something else
2.1. Not wanting to export the actual class name
2.2. Being able to return an instance of some other class, usually a subclass
Convenient shorthand for a specific class
I striked always, because it seems proponents to constructor functions for CLOS objects don't necessarily want to hide the protocol that make-instance follows (allocate-instance, initialize-instance → shared-initialize) to implementers or extenders of the API or framework, although they might want to hide it to the consumers of the API or framework.
For something faster, you might want to access slots directly, but that doesn't use accessor methods, and hence doesn't support side-effects, e.g. :before and :after methods:
(defmacro gets (class var object)
(let ((object-var (gensym)))
`(let ((,object-var ,object))
(declare (optimize (speed 3) (safety 0) (debug 0))
(type ,class ,object-var))
(slot-value ,object-var ',var))))
This might be a direct slot access on some implementations.
Finally, you also have with-slots and with-accessors in the standard.
Try playing with something like this:
(let ((a 'a)
(dash '-)
(b 'b))
`(,a,dash,b))
The other possibilities is to use intern, or more user friendly, alexandria's symbolicate.

Function name and dynamic binding in Common Lisp

I'm reading Peter Norvig's Paradigms of AI. In chapter 6.2, the author uses code like below (not the original code, I picked out the troubling part):
Code Snippet:
(progv '(op arg) '(1+ 1)
(eval '(op arg)))
As the author's original intent, this code should return 2, but in sbcl 1.1.1, the interpreter is apparently not looking up op in the environment, throwing out op: undefined function.
Is this implementation specific? Since the code must have been tested on some other lisp.
p.s Original code
You probably mean
(progv '(op arg) '(1+ 1)
(eval '(funcall op arg)))
Edit(2013-08-21):
PAIP was written in pre-ANSI-Common-Lisp era, so it's possible the code
there contains a few noncompliances wrt the standard. We can make
the examples work with the following revision:
(defun match-if (pattern input bindings)
"Test an arbitrary expression involving variables.
The pattern looks like ((?if code) . rest)."
(and (eval (reduce (lambda (code binding)
(destructuring-bind (var . val) binding
(subst val var code)))
bindings :initial-value (second (first pattern))))
(pat-match (rest pattern) input bindings)))
;; CL-USER> (pat-match '(?x ?op ?y is ?z (?if (eql (?op ?x ?y) ?z))) '(3 + 4 is 7))
;; ((?Z . 7) (?Y . 4) (?OP . +) (?X . 3) (T . T))
;; CL-USER> (pat-match '(?x ?op ?y (?if (?op ?x ?y))) '(3 > 4))
;; NIL
Elements in first positions are not looked up as values, but as functions and there is no concept of dynamic binding in the function namespace.
I'd say after a quick look that the original code was designed to evaluate in a context like
(progv '(x y) '(12 34)
(eval '(> (+ x y) 99)))
i.e. evaluating a formula providing substitution for variables, not for function names.
The other answers so far are right, in that the actual form being evaluated is not the variables being bound by progv (simply (op arg)), but none have mentioned what is being evaluated. In fact, the comments in the code you linked to provide a (very) short explanation (this is the only code in that file that uses progv):
(defun match-if (pattern input bindings)
"Test an arbitrary expression involving variables.
The pattern looks like ((?if code) . rest)."
;; *** fix, rjf 10/1/92 (used to eval binding values)
(and (progv (mapcar #'car bindings)
(mapcar #'cdr bindings)
(eval (second (first pattern))))
(pat-match (rest pattern) input bindings)))
The idea is that a call to match-if gets called like
(match-if '((?if code) . rest) input ((v1 val1) (v2 val2) ...))
and eval is called with (second (first pattern)), which the value of code. However, eval is called within the progv that binds v1, v2, &c., to the corresponding val1, val2, &c., so that if any of those variables appear free in code, then they are bound when code is evaluated.
Problem
The problem that I see here is that, by the code we can't tell if the value is to be saved as the variable's symbol-value or symbol-function. Thus when you put a + as a value to some corresponding variable, say v, then it'll always be saved as the symbol-value of var, not it's symbol-function.
Therefore when you'll try to use it as, say (v 1 2) , it won't work. Because there is no function named v in the functions' namespace(see this).
So, what to do?
A probable solution can be explicit checking for the value that is to be bound to a variable. If the value is a function, then it should be bound to the variable's function value. This checking can be done via fboundp.
So, we can make a macro functioner and a modified version of match-if. functioner checks if the value is a function, and sets it aptly. match-if does the dynamic local bindings, and allows other code in the scope of the bound variables.
(defmacro functioner (var val)
`(if (and (symbolp ',val)
(fboundp ',val))
(setf (symbol-function ',var) #',val)
(setf ,var ,val)))
(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))))

How can I SETF an element in a tree by an accessor?

We've been using Lisp in my AI course. The assignments I've received have involved searching and generating tree-like structures. For each assignment, I've ended up writing something like:
(defun initial-state ()
(list
0 ; score
nil ; children
0 ; value
0)) ; something else
and building my functions around these "states", which are really just nested lists with some loosely defined structure.
To make the structure more rigid, I've tried to write accessors, such as:
(defun state-score ( state )
(nth 2 state))
This works for reading the value (which should be all I need to do in a nicely functional world. However, as time crunches, and I start to madly hack, sometimes I want a mutable structure). I don't seem to be able to SETF the returned ...thing (place? value? pointer?).
I get an error with something like:
(setf (state-score *state*) 10)
Sometimes I seem to have a little more luck writing the accessor/mutator as a macro:
(defmacro state-score ( state )
`(nth 2 ,state))
However I don't know why this should be a macro, so I certainly shouldn't write it as a macro (except that sometimes it works. Programming by coincidence is bad).
What is an appropriate strategy to build up such structures?
More importantly, where can I learn about whats going on here (what operations affect the memory in what way)?
Use CLOS for data structures
The best way out of this is to quickly learn the basics of CLOS.
(defclass state ()
((score :accessor state-score :initform 0)
(children :accessor state-children :initform nil)
(value :accessor state-value :initform 0)))
(defun make-initial-state ()
(make-instance 'state))
(defparameter *state* (make-initial-state))
(setf (state-score *state*) 10)
For most application code avoid structures
For most code avoid structures - use them only when you need them and know why. Use CLOS classes instead.
DEFSTRUCT also works with lists
If you really want to use lists, one option is to use the DEFSTRUCT macro with lists and have it define all the functions:
(defstruct (state (:type list))
(score 0)
(children nil)
(value 0))
Above, the :type option tells DEFSTRUCT to use a list instead a structure.
? (defparameter *state* (make-state))
*STATE*
? (setf (state-score *state*) 10)
10
(make-state) returns a list of three items.
We can write setter functions
If you want to write code by hand, then you can write setter functions:
(defun get-my-score (state)
(first state))
(defun (setf get-my-score) (score state)
(setf (first state) score))
Above defines a SETF function. The name of the function is actually a list. The parameters for this function have to be first the new-value and then the thing to set.
? (setf *state* (list 0 nil 0))
(0 NIL 0)
? (setf (get-my-score *state*) 10)
10
? *state*
(10 NIL 0)
The Common Lisp HyperSpec defines what places are and how to work with them. I would guess that this is not the best source to learn from and possibly it is best explained in some introductory Lisp book.
You can use something like this:
(defun get-score (state)
(nth 0 state)) ; This corresponds to the comments in the init function
(defun set-score (state new-value)
(setf (nth 0 state) new-value))
(defsetf get-score set-score)
This way, any time you write (setf (get-score something) else) it will be translated to (set-score something else).
Use defstruct:
> (defstruct state score children val something-else)
STATE
> (setq initial-state (make-state :score 0 :children nil :val 0 :something-else nil))
#S(STATE :SCORE 0 :CHILDREN NIL :VAL 0 :SOMETHING-ELSE NIL)
> (state-score initial-state) ; current score
0
> (setf (state-score initial-state) 10) ; set new score
10
> (state-score initial-state)
10
This happens because setf is a macro. When you define state-score as a macro, setf sees:
(setf (nth 2 state) value)
And knows what to do since it can use nth as a place to store values. On the other hand, when state-score is a function, setf just sees a value returned, and can't do anything about it.
Read more about how setf works and its concept of places for a deeper understanding. Here's an interesting tutorial that says:
The setf special form uses its first
argument to define a place in memory,
evaluates its second argument, and
stores the resulting value in the
resulting memory location