Re: Call by value, but (please check my hypothesis)



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.

.



Relevant Pages

  • Re: Doubly-linked list implementation?
    ... How about dotted lists: (value previous. ... pointer type (a reference can only point to a known object or nil, ... Why doesn't Lisp have references? ... (setf (next-of x) ...
    (comp.lang.lisp)
  • Re: newbie Q: opposite of quote
    ... (eval (quote a)) ... a first Common Lisp lesson. ... you can use lists as short as you want. ... symbols, set, setq, setf, psetq, psetf. ...
    (comp.lang.lisp)
  • Re: Maintain list of attached event handlers (.Net 1.1)
    ... Your requirement to unsubscribe when the event fires is completely independent of how you unsubscribe other events later. ... A basic rule of event management is that when you subscribe the first handler, the reference to the event has to be instantiated. ... While you didn't actually post any code that showed such an enumeration, I will take as granted that somewhere you actually do. ... It's simple, it works, and is MORE performant than trying to maintain a list or lists or other data structures as various events are raised and unsubscribed from. ...
    (microsoft.public.dotnet.framework)
  • Bottleneck rule
    ... groups similar strings together. ... prints out an intermediate store file to view intermediate results. ... (setf (aref store i 0) ... ;;Print output the lists of grouped strings and counts. ...
    (comp.lang.lisp)
  • Re: [PATCH 2.6.23.14] SCSI : scsi_device_lookup/scsi_device_lookup_by_target return NULL for an exis
    ... because there is some outstanding command holding a reference to it. ... scanning will go ahead and try to add a new scsi_device to the devices lists. ... the consensus was to resurrect the sdev from the SDEV_DEL state back ... - that patches for the resurrection where implemented post this thread ...
    (Linux-Kernel)