Lisp HUG Maillist Archive

Newbie question

Hi!

I'm trying to work through some of the examples in "Object-Oriented
Progamming in Common Lisp" by Sonja Keene, and I'm kind-of stuck with
the example on pg. 38, which uses a function "sys:%pointer" to obtain
the address of an object in memory. The book states that this function
isn't part of Common Lisp, but is defined in some implementations. I'm
guessing that the Lisp Works implementation doesn't define it (I got
the error "Symbol "%POINTER" not found at all in the SYSTEM package"
when I tried it). Is there some other way to obtain the address of an
object? I tried using "(string ...)" and "(coerce ... '(string))", but
neither worked.

Thanks.

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Newbie question

David <dfkettle@gmail.com> writes:

> Hi!
>
> I'm trying to work through some of the examples in "Object-Oriented
> Progamming in Common Lisp" by Sonja Keene, and I'm kind-of stuck with
> the example on pg. 38, which uses a function "sys:%pointer" to obtain
> the address of an object in memory. The book states that this function
> isn't part of Common Lisp, but is defined in some implementations. I'm
> guessing that the Lisp Works implementation doesn't define it (I got
> the error "Symbol "%POINTER" not found at all in the SYSTEM package"
> when I tried it). Is there some other way to obtain the address of an
> object? I tried using "(string ...)" and "(coerce ... '(string))", but
> neither worked.

It's not really interesting to have the address of an object.  IIRC, the
book mentions that it can even change between garbage collection, so
while it may be unique identifier of an object at a given time, it may
not stay unique during the execution of the program. (And since printing
an object may invoke the garbage collector, this address may be wrong as
soon as it's obtained).

Nonetheless, it's pretty to have rows of numbers.

Now you have two choices if you want to get that kind of numbers in a
conforming way:

- generate them  yourself:

     (defvar *last-address* #x1000000)
     (defvar *objects-with-addresses* (make-hash-table)
             "maps objects to addresses.")
     (defun %pointer (object)
        (format nil "#x~8,'0X"
            (or (gethash object *objects-with-addresses*)
                (setf (gethash object *objects-with-addresses*)
                      (incf *last-address* 8)))))

     (defclass object () ())
     (let* ((a (make-instance 'object))
            (b (make-instance 'object))
            (c (make-instance 'object))
            (d (list a b c a b c)))
       (mapcar '%pointer d))
     --> ("#x01000020" "#x01000028" "#x01000030" "#x01000020" "#x01000028" "#x01000030")


    The inconvenient of this solution is that it registers the objects into
    a hash-table, preventing their garbage collection, or you would have to
    use an extension such as weak hash tables.


- use CL:PRINT-UNREADABLE-OBJECT to obtain those "addresses".

      (defun %pointer (object)
        "
      RETURN:         A string containing the object identity as printed by
                      PRINT-UNREADABLE-OBJECT.
      "
        (let ((*print-readably* nil))
          (let ((ident
                 (with-output-to-string (stream)
                   (print-unreadable-object (object stream :type nil :identity t)))))
            (string-trim " " (subseq ident 2 (1- (length ident)))))))


     (let* ((a (make-instance 'object))
            (b (make-instance 'object))
            (c (make-instance 'object))
            (d (list a b c a b c)))
       (mapcar '%pointer d))
     --> ("#x302001D3E92D" "#x302001D3E8FD" "#x302001D3E8CD"
          "#x302001D3E92D" "#x302001D3E8FD" "#x302001D3E8CD")


Since the format of print-unreadable-object imposes #< and >, this
%pointer function should be conforming and return similar results
everywhere.  Notice, the standard doesn't specify the format of object
identities, it's not necessarily anything readable, so we leave it as
string.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Newbie question

Unable to parse email body. Email id is 11664

Re: Newbie question

On 17 Jul 2012, at 16:08, David wrote:

> 
> Hi!
> 
> I'm trying to work through some of the examples in "Object-Oriented
> Progamming in Common Lisp" by Sonja Keene, and I'm kind-of stuck with
> the example on pg. 38, which uses a function "sys:%pointer" to obtain
> the address of an object in memory. The book states that this function
> isn't part of Common Lisp, but is defined in some implementations. 

In LW an equivalent is SYSTEM:OBJECT-ADDRESS, and note that the manual explicitly says: "Note that the address is likely to change during garbage collection so this integer should be used for debugging purposes only." (And indeed you can see things move around).

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Newbie question

Thanks, everyone. Sounds like it's a bad practice in the first place,
I'm not sure why it's in the book. It seems somewhat peripheral to the
subject of the book (CLOS), anyway. But the example works now.

On Tue, Jul 17, 2012 at 12:32 PM, Dave Fox <davef@lispworks.com> wrote:
>
>  > Hi!
>  >
>  > I'm trying to work through some of the examples in "Object-Oriented
>  > Progamming in Common Lisp" by Sonja Keene, and I'm kind-of stuck with
>  > the example on pg. 38, which uses a function "sys:%pointer" to obtain
>  > the address of an object in memory. The book states that this function
>  > isn't part of Common Lisp, but is defined in some implementations. I'm
>  > guessing that the Lisp Works implementation doesn't define it (I got
>  > the error "Symbol "%POINTER" not found at all in the SYSTEM package"
>  > when I tried it). Is there some other way to obtain the address of an
>  > object?
>
> Yes, SYS:OBJECT-ADDRESS
>
>
>
> --
> Dave Fox
> LispWorks Ltd
> http://www.lispworks.com/
>
> Registered Office: St John's Innovation Centre, Cowley Road, Cambridge CB4 0WS
> Registered in England: No. 5114963
> EC VAT ID: GB 833329531

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Newbie question

I would suggest using the macro 'PRINT-UNREADABLE-OBJECT'.

this macro has a keyword argument that when set to 'T' will typically
print the storage address of the object

the example in p38 can be done using the macro as follows:

(defmethod print-object ((l lock) stream)
               (print-unreadable-object (l stream :type t :identity t)
                 (format stream "~A" (if (slot-boundp l 'name)
                                       (lock-name l)
                                       "(no name)"))))

HIH

Ala'a

On Tue, Jul 17, 2012 at 7:08 PM, David <dfkettle@gmail.com> wrote:
>
>
> Hi!
>
> I'm trying to work through some of the examples in "Object-Oriented
> Progamming in Common Lisp" by Sonja Keene, and I'm kind-of stuck with
> the example on pg. 38, which uses a function "sys:%pointer" to obtain
> the address of an object in memory. The book states that this function
> isn't part of Common Lisp, but is defined in some implementations. I'm
> guessing that the Lisp Works implementation doesn't define it (I got
> the error "Symbol "%POINTER" not found at all in the SYSTEM package"
> when I tried it). Is there some other way to obtain the address of an
> object? I tried using "(string ...)" and "(coerce ... '(string))", but
> neither worked.
>
> Thanks.
>
> _______________________________________________
> Lisp Hug - the mailing list for LispWorks users
> lisp-hug@lispworks.com
> http://www.lispworks.com/support/lisp-hug.html
>

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Newbie question

Side question if i tried the following in the repl (LWL 6.1 - x86 32-bit)

(defclass x () ()) =>  #<STANDARD-CLASS X 200A7C83>
(sys:object-address *) => 537558144
(format nil "~X" *) => "200A7C80"

The last one gave an address that differ from the address in the first result with '3'.

and using the documentation example
(let ((gf #'initialize-instance))
               (format t "address = ~X~%gf = ~S" 
                  (sys:object-address gf) gf))

I get
address = 2080F9E0
gf = #<STANDARD-GENERIC-FUNCTION INITIALIZE-INSTANCE 2080F9E2>
NIL

which seems to differ by '2'

Is this a bug?


Ala'a


On Tue, Jul 17, 2012 at 8:32 PM, Dave Fox <davef@lispworks.com> wrote:


 > Hi!
 >
 > I'm trying to work through some of the examples in "Object-Oriented
 > Progamming in Common Lisp" by Sonja Keene, and I'm kind-of stuck with
 > the example on pg. 38, which uses a function "sys:%pointer" to obtain
 > the address of an object in memory. The book states that this function
 > isn't part of Common Lisp, but is defined in some implementations. I'm
 > guessing that the Lisp Works implementation doesn't define it (I got
 > the error "Symbol "%POINTER" not found at all in the SYSTEM package"
 > when I tried it). Is there some other way to obtain the address of an
 > object?

Yes, SYS:OBJECT-ADDRESS



--
Dave Fox
LispWorks Ltd
http://www.lispworks.com/

Registered Office: St John's Innovation Centre, Cowley Road, Cambridge CB4 0WS
Registered in England: No. 5114963
EC VAT ID: GB 833329531

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Newbie question

On Tue, Jul 17, 2012 at 12:50 PM, Ala'a Mohammad <amalawi@gmail.com> wrote:
> Side question if i tried the following in the repl (LWL 6.1 - x86 32-bit)
>
> (defclass x () ()) =>  #<STANDARD-CLASS X 200A7C83>
> (sys:object-address *) => 537558144
> (format nil "~X" *) => "200A7C80"
>
> The last one gave an address that differ from the address in the first
> result with '3'.
>
> and using the documentation example
>
> (let ((gf #'initialize-instance))
>
>                (format t "address = ~X~%gf = ~S"
>
>                   (sys:object-address gf) gf))
>
>
> I get
>
> address = 2080F9E0
> gf = #<STANDARD-GENERIC-FUNCTION INITIALIZE-INSTANCE 2080F9E2>
>
> NIL
>
> which seems to differ by '2'
>
>
> Is this a bug?

It's probably tagging in the low bits of the object.  Lots (most?
all?) lisps do something like this.

ECL : http://ecls.sourceforge.net/new-manual/ch33.html
SBCL : http://sbcl-internals.cliki.net/tag%20bit
a list for a bunch of implementations : http://lars.nocrew.org/lisptags.html

More generally, see tagged pointers:
http://en.wikipedia.org/wiki/Tagged_pointer

//JT
-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Newbie question

On Tue, Jul 17, 2012 at 9:06 PM, Joshua TAYLOR <jtaylor@alum.rpi.edu> wrote:
>
> On Tue, Jul 17, 2012 at 12:50 PM, Ala'a Mohammad <amalawi@gmail.com> wrote:
>> Side question if i tried the following in the repl (LWL 6.1 - x86 32-bit)
>>
>> (defclass x () ()) =>  #<STANDARD-CLASS X 200A7C83>
>> (sys:object-address *) => 537558144
>> (format nil "~X" *) => "200A7C80"
>>
>> The last one gave an address that differ from the address in the first
>> result with '3'.
>>
>> and using the documentation example
>>
>> (let ((gf #'initialize-instance))
>>
>>                (format t "address = ~X~%gf = ~S"
>>
>>                   (sys:object-address gf) gf))
>>
>>
>> I get
>>
>> address = 2080F9E0
>> gf = #<STANDARD-GENERIC-FUNCTION INITIALIZE-INSTANCE 2080F9E2>
>>
>> NIL
>>
>> which seems to differ by '2'
>>
>>
>> Is this a bug?
>
> It's probably tagging in the low bits of the object.  Lots (most?
> all?) lisps do something like this.

from LW 6.1 sys:object-address documentation:

"the address returned by sys:object-address **is the same** as the one
printed by the print-object method"

emphasis is mine.

check the doc here:
http://www.lispworks.com/documentation/lw61/LW/html/lw-1410.htm#marker-887327

--
Ala'a

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Newbie question

On Tue, Jul 17, 2012 at 1:35 PM, Ala'a Mohammad <amalawi@gmail.com> wrote:
> On Tue, Jul 17, 2012 at 9:06 PM, Joshua TAYLOR <jtaylor@alum.rpi.edu> wrote:
>>
>> On Tue, Jul 17, 2012 at 12:50 PM, Ala'a Mohammad <amalawi@gmail.com> wrote:
>>> Side question if i tried the following in the repl (LWL 6.1 - x86 32-bit)
>>>
>>> (defclass x () ()) =>  #<STANDARD-CLASS X 200A7C83>
>>> (sys:object-address *) => 537558144
>>> (format nil "~X" *) => "200A7C80"
>>>
>>> The last one gave an address that differ from the address in the first
>>> result with '3'.
>>>
>>> and using the documentation example
>>>
>>> (let ((gf #'initialize-instance))
>>>
>>>                (format t "address = ~X~%gf = ~S"
>>>
>>>                   (sys:object-address gf) gf))
>>>
>>>
>>> I get
>>>
>>> address = 2080F9E0
>>> gf = #<STANDARD-GENERIC-FUNCTION INITIALIZE-INSTANCE 2080F9E2>
>>>
>>> NIL
>>>
>>> which seems to differ by '2'
>>>
>>>
>>> Is this a bug?
>>
>> It's probably tagging in the low bits of the object.  Lots (most?
>> all?) lisps do something like this.
>
> from LW 6.1 sys:object-address documentation:
>
> "the address returned by sys:object-address **is the same** as the one
> printed by the print-object method"
>
> emphasis is mine.
>
> check the doc here:
> http://www.lispworks.com/documentation/lw61/LW/html/lw-1410.htm#marker-887327

Ah, I see what you mean.  Sounds like a documentation bug, though I'd
point out that the relevant text might be read as a description of the
example code rather than a general claim (since its in the example
section, and there's no mention of object-address/print-object
correspondence in the rest of the description).  That said, if the
example doesn't work, something should  be fixed (probably the
documentation).  //JT

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Updated at: 2020-12-10 08:36 UTC