Re: Call by value, but (please check my hypothesis)
- From: "Kaz Kylheku" <kkylheku@xxxxxxxxx>
- Date: 12 Oct 2005 16:03:45 -0700
tin gherdanarra wrote:
> Dear Lispniks,
>
> I understand that Lisp does not pass around
> references in the sense that only "handles"
In general, objects are passed by reference in Lisp. When something
else is the case, it is an optimization that can be done when an object
fits into a cell. This is done with small integers or characters, for
instance.
> to lists (as python does, for example).
A Lisp list isn't a container abstraction. It's an object that arises
when cons cells are used in accordance with a certain convention.
An empty list is the symbol NIL. That is to say, the symbol named "NIL"
in the "COMMON-LISP" package. (NIL may be implemented as an actual
reference to this symbol, or as a special bit pattern that is made to
behaves as a reference to that symbol whenever called upon to do so).
A proper list of 1 element is implemented as a reference to a cons cell
whose CAR field contains that element, and whose CDR field is NIL.
A proper list of N elements, where N > 0, is implemented as a cons
cell, whose CAR field holds the first element of the list, and whose
CDR field refers to the remaining list of N - 1 elements (the list of 0
elements being NIL).
> This has the consequence that if I do a
> (setf (getf '(a 0 b 1 c 2 d 3) 'b) 99) it
> is NOT that getf returns a handle to
> the "1" and the setf crawls after the spot
> in memory to replace it with a "2".
That is correct. SETF actually understands the syntax of the (GETF
....) expression, and knows what to do with it.
But note that it's illegal to be modifying a list literal.
> setf looks into the generalized variable
> '(getf (a 0 b 1 c 2 d 3) b) and determines
> that it has to pull a replacd on the
> '(a 0 b 1 c 2 d 3) to replace the 1 with
> a 2. In other words, setf uses something
> like a case to lookup what it has to do
> with getf...
Yes. SETF performs a lookup through its large repertoire of registered
expanders. It has an expander for GETF which tells it exactly what to
do.
> If I have function that does a getf, I
> have to get this function into
> setf's lookup table. This can be done
> with "define-modify-macro".
Correct. A use of GETF wrapped in a function hides the GETF.
This is exactly like the C language. In C, *E is an lvalue, if
expression E is a pointer to something. You can assign to it using *E =
2.
If you wrap that inside a function, you can't assign through it any
longer:
int x() { return *E; }
x() = 2; /* oops */
The = operator understands the /form/ of the left hand side; only
certain forms can be lvalues, and they are only considered lvalues when
they are to the left of an assignment operator.
The return value of a function isn't an lvalue, so that doesn't work.
> This, however, leads to problems if
> the nesting level of an item in a
> tree is not known in advance. The macro
> is defined and carved in stone at compile-time.
> This means if I have a list like
> (a 0 (b 1 c 2 (d 3 (e 4) f 5) g 6)),
> I cannot walk the tree recursively and
> change to find a certain item and change
> it with setf. This is because I cannot
> make a generalized variable (since it
> is not known at macro compile time how
> deep I will want to go). Is this correct?
> Is there a way out?
That is not correct. You just need a SETF expander that understands
parameters. The NTH function is an example. You don't know which
element of the list will be selected; it's a parameter that is not
necessarily known at compile time.
(defvar *list* (list 1 2 3))
(defvar *index* 1)
(setf (nth *index* *list*) 2)
The macro expands to code that can handle the parameter.
If you can write a function that will walk the tree to some specified
place and store an item there, you can develop the SETF veneer over it.
Try this:
(defun three-level-set (list index-0 index-1 index-2 item)
(setf (nth index-2 (nth index-2 (nth index-0 list))) item))
(defvar *list* (copy-tree '(((a b) (c d)) ((e f) (g h)))))
(three-level-set *list* 1 1 0 'z)
That should replace the G symbol by Z: choose the second sublist,
second sublist within that, replace first item by Z.
The SETF works through the nested NTH expressions.
.
- References:
- Call by value, but (please check my hypothesis)
- From: tin gherdanarra
- Call by value, but (please check my hypothesis)
- Prev by Date: Re: EQ perplexity
- Next by Date: Re: SeaFunc meets Oct. 18
- Previous by thread: Re: Call by value, but (please check my hypothesis)
- Next by thread: [no subject]
- Index(es):
Relevant Pages
|