From: MishoM
Subject: Modifying data with inspect in SBCL - is it possible?
Date: 
Message-ID: <b066ff7d-42da-4038-87d6-24392412cc07@d25g2000prn.googlegroups.com>
Hi,

I've been trying out the inspect implementation in SBCL and I couldn't
find a way to modify the inspected data through the sb-ext:*inspected*
symbol. I know that in most cases I could just modify the data
directly (because I know what I'm inspecting), but I was trying  (just
out of curiousity) to modify a variable bound by a closure and it is
only accessible through the functions from the closure.

Also, how easy is it to do this with inspect in other CL
implementations?

Mihail Mihaylov

From: Joshua Taylor
Subject: Re: Modifying data with inspect in SBCL - is it possible?
Date: 
Message-ID: <b34e8144-4a04-47e2-987d-5f0ebcca488c@r36g2000vbr.googlegroups.com>
On Apr 2, 3:45 am, MishoM <···············@gmail.com> wrote:
> Hi,
>
> I've been trying out the inspect implementation in SBCL and I couldn't
> find a way to modify the inspected data through the sb-ext:*inspected*
> symbol. I know that in most cases I could just modify the data
> directly (because I know what I'm inspecting), but I was trying  (just
> out of curiousity) to modify a variable bound by a closure and it is
> only accessible through the functions from the closure.
>
> Also, how easy is it to do this with inspect in other CL
> implementations?
>
> Mihail Mihaylov


It can be done in LispWorks, and fairly easily too.  I did it in the
GUI inspector first, but here's the REPL version:


CL-USER 1 > (defparameter *f* (let ((x 0)) (lambda () x)))
*F*

CL-USER 2 > (funcall *f*)
0

CL-USER 3 > (inspect *f*)

#<anonymous interpreted function 214B4702> is a SYSTEM::FUNCALLABLE
CODE           #<Code Vector [7]>
CONSTANTS      (SYSTEM::%LEXICAL-CLOSURE% (LAMBDA NIL X) ((X . 0)) NIL
NIL ...)

CL-USER 4 : Inspect 1 > constants

(SYSTEM::%LEXICAL-CLOSURE% (LAMBDA NIL X) ((X . 0)) NIL NIL ...) is a
LIST
0      SYSTEM::%LEXICAL-CLOSURE%
1      (LAMBDA NIL X)
2      ((X . 0))
3      NIL
4      NIL
5      NIL

CL-USER 5 : Inspect 2 > 2

((X . 0)) is a LIST
0      (X . 0)

CL-USER 6 : Inspect 3 > 0

(X . 0) is a CONS
CAR      X
CDR      0

CL-USER 7 : Inspect 4 > :s cdr 32

CL-USER 8 : Inspect 4 > :q
(X . 32)

CL-USER 9 > (funcall *f*)
32


The direct SBCL parallel seems less promising.  It's not clear what
would be modifiable:


* (defparameter *f* (let ((x 0)) (lambda () x)))

*F*
* (funcall *f*)

0
* (inspect *f*)

The object is a FUNCTION named (LAMBDA ()).
0. Lambda-list: NIL
1. Ftype: (FUNCTION NIL (VALUES (INTEGER 0 0) &OPTIONAL))
> 1

The object is a proper list of length 3.
0. 0: FUNCTION
1. 1: NIL
2. 2: (VALUES (INTEGER 0 0) &OPTIONAL)
> :q


However, it looks like SBCL recognizes that there's no way for x to
change.  But look what happens when x can change:

* (defparameter *f* (let ((x 0)) (values (lambda () x) (lambda ()
(incf x)))))

*F*
* (funcall *f*)

0
* (inspect *f*)

The object is a CLOSURE named (LAMBDA ()).
0. Lambda-list: NIL
1. Ftype: (FUNCTION NIL (VALUES UNSIGNED-BYTE &OPTIONAL))
2. Closed over values: (#<value cell 0 {11C1B7CF}>)
> 2

The object is a CONS.
0. CAR: #<value cell 0 {11C1B7CF}>
1. CDR: NIL
> 0

The object is an ATOM:
  #<value cell 0 {11C1B7CF}>


Now, I'm not sure whether there's a way to change the value in a value
cell, but I bet some SBCL people can chime in and tell.  It seems like
it would still depend on something like

(setf (value-cell-value sb-ext:*inspected*) <new-value>)

if it is indeed possible.  It would still seem to depend on using sb-
ext:*inspected*.

//JT
From: Thomas A. Russ
Subject: Re: Modifying data with inspect in SBCL - is it possible?
Date: 
Message-ID: <ymi4ox67w6t.fsf@blackcat.isi.edu>
MishoM <···············@gmail.com> writes:

> Hi,
> 
> I've been trying out the inspect implementation in SBCL and I couldn't
> find a way to modify the inspected data through the sb-ext:*inspected*
> symbol. I know that in most cases I could just modify the data
> directly (because I know what I'm inspecting), but I was trying  (just
> out of curiousity) to modify a variable bound by a closure and it is
> only accessible through the functions from the closure.

Well, with inspect you are not likely to be able to access the variable
in the closure.  For modifying "local" variables like that you most
often need to use the debugger instead.

Of is it the case that you are inspecting a closure and want to change
the value?  If so, there is still the issue of how you get the variable
binding to be able to modify it.  It may be the case that there isn't
really any accessor for mutating the closed-over values of the closure.
In that case, you won't be able to do it.

The simplest method would, in fact, be to use the functions inside the
closure to make the change.

> Also, how easy is it to do this with inspect in other CL
> implementations?

Of course, one has to ask why you want or need to do it this way.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ·····@franz.com
Subject: Re: Modifying data with inspect in SBCL - is it possible?
Date: 
Message-ID: <4422bfa4-a573-43b9-a44b-db530d1c76d8@f19g2000yqh.googlegroups.com>
On Apr 2, 12:45 am, MishoM <···············@gmail.com> wrote:
> Hi,
>
> I've been trying out the inspect implementation in SBCL and I couldn't
> find a way to modify the inspected data through the sb-ext:*inspected*
> symbol. I know that in most cases I could just modify the data
> directly (because I know what I'm inspecting), but I was trying  (just
> out of curiousity) to modify a variable bound by a closure and it is
> only accessible through the functions from the closure.
>
> Also, how easy is it to do this with inspect in other CL
> implementations?

In Allegro CL, it is trivial.  The inspect function can be invoked as
a top-level :inspect command (abbreviated as far down as :in) and
comes paired with the :istep command (abbreviated as far down as :i).
The :istep command also impements sub-commands which allow navigation
within objects, as well as raw vs cooked modes for pesentation.  Also,
the 'set' sub-command allows the stting of fields where setting is
appropriate (and sometimes when it is not - another case of providing
enough rope to hang yourself :-)  So, for example:

CL-USER(1): (inspect 'a)
A NEW The symbol A @ #x7172e86f
  which is an INTERNAL symbol in the COMMON-LISP-USER package
   0 type ---------> Bit field: #x07
   1 flags --------> Bit field: #x00
   2 package ------> The COMMON-LISP-USER package
   3 value --------> ..unbound..
   4 function -----> ..funbound..
   5 hash ---------> Bit field: #x6f5750
   6 name ---------> A simple-string (1) "A"
   7 plist --------> The symbol NIL
[1i] CL-USER(2): :i set value 10
A NEW The symbol A @ #x7172e86f
  which is an INTERNAL symbol in the COMMON-LISP-USER package
   0 type ---------> Bit field: #x07
   1 flags --------> Bit field: #x00
   2 package ------> The COMMON-LISP-USER package
   3 value --------> fixnum 10 [#x00000028]
   4 function -----> ..funbound..
   5 hash ---------> Bit field: #x6f5750
   6 name ---------> A simple-string (1) "A"
   7 plist --------> The symbol NIL
[1i] CL-USER(3): a
10
[1i] CL-USER(4): :in #'print-object
A TENURED #<STANDARD-GENERIC-FUNCTION PRINT-OBJECT>
  lambda-list: ((EXCL::X SYS::AUGMENTABLE-ENVIRONMENT-BASE) STREAM)
   0 Class --------> #<MOP:FUNCALLABLE-STANDARD-CLASS
                       STANDARD-GENERIC-FUNCTION>
   1 PLIST --------> The symbol NIL
   2 FLAGS --------> fixnum 1 [#x00000004]
   3 NAME ---------> The symbol PRINT-OBJECT
   4 METHODS ------> (# # # # # # # # # # ...), a proper list with 64
elements
   5 METHOD-CLASS -> #<STANDARD-CLASS STANDARD-METHOD>
   6 METHOD-COMBINATION -> #<EXCL::STANDARD-METHOD-COMBINATION @
                             #x7111a91a>
   7 ARG-INFO -----> simple T vector (7) = #(EXCL::ARG-INFO T ...)
[2i] CL-USER(5): :i raw
A TENURED #<STANDARD-GENERIC-FUNCTION PRINT-OBJECT>
  lambda-list: ((EXCL::X SYS::AUGMENTABLE-ENVIRONMENT-BASE) STREAM)
   0 excl-type ----> Bit field: #x08
   1 flags --------> Bit field: #x89
   2 start --------> Bit field: #x0196982c
   3 hash ---------> Bit field: #x0000242c
   4 symdef -------> The symbol PRINT-OBJECT
   5 code ---------> short simple CODE vector (7) = #(30347 65298
62054 ...)
   6 formals ------> ((EXCL::X ...) ...), a proper list with 2
elements
   7 disc-type ----> The symbol :CACHING
   8 disc-cache ---> simple T vector (32) = #(0 NIL ...)
   9 disc-result --> The symbol NIL
  10 fin-fun ------> #<Closure (:DISCRIMINATOR
                                (:CACHING (CLASS T) NIL))
                       @ #x71738d1a>
  11 wrapper ------> simple T vector (7) = #(5098920 T ...)
  12 slots --------> simple T vector (7) = #(NIL 1 PRINT-OBJECT ...)
[2i] CL-USER(6): :i set 6 '(bogus)
A TENURED #<STANDARD-GENERIC-FUNCTION PRINT-OBJECT>
  lambda-list: (BOGUS)
   0 excl-type ----> Bit field: #x08
   1 flags --------> Bit field: #x89
   2 start --------> Bit field: #x0196982c
   3 hash ---------> Bit field: #x0000242c
   4 symdef -------> The symbol PRINT-OBJECT
   5 code ---------> short simple CODE vector (7) = #(30347 65298
62054 ...)
   6 formals ------> (BOGUS), a proper list with 1 element
   7 disc-type ----> The symbol :CACHING
   8 disc-cache ---> simple T vector (32) = #(0 NIL ...)
   9 disc-result --> The symbol NIL
  10 fin-fun ------> #<Closure (:DISCRIMINATOR
                                (:CACHING (CLASS T) NIL))
                       @ #x7158f45a>
  11 wrapper ------> simple T vector (7) = #(5098920 T ...)
  12 slots --------> simple T vector (7) = #(NIL 1 PRINT-OBJECT ...)
[2i] CL-USER(7): (arglist 'print-object)
(BOGUS)
T
[2i] CL-USER(8):

Enjoy.

Duane
From: MishoM
Subject: Re: Modifying data with inspect in SBCL - is it possible?
Date: 
Message-ID: <cd02aad8-8579-4f8e-b579-ece95391e512@j39g2000yqn.googlegroups.com>
On Apr 2, 11:40 pm, ·····@franz.com wrote:
> On Apr 2, 12:45 am, MishoM <···············@gmail.com> wrote:
>
> > Hi,
>
> > I've been trying out the inspect implementation in SBCL and I couldn't
> > find a way to modify the inspected data through the sb-ext:*inspected*
> > symbol. I know that in most cases I could just modify the data
> > directly (because I know what I'm inspecting), but I was trying  (just
> > out of curiousity) to modify a variable bound by a closure and it is
> > only accessible through the functions from the closure.
>
> > Also, how easy is it to do this with inspect in other CL
> > implementations?
>
> In Allegro CL, it is trivial.  The inspect function can be invoked as
> a top-level :inspect command (abbreviated as far down as :in) and
> comes paired with the :istep command (abbreviated as far down as :i).
> The :istep command also impements sub-commands which allow navigation
> within objects, as well as raw vs cooked modes for pesentation.  Also,
> the 'set' sub-command allows the stting of fields where setting is
> appropriate (and sometimes when it is not - another case of providing
> enough rope to hang yourself :-)  So, for example:
>
> CL-USER(1): (inspect 'a)
> A NEW The symbol A @ #x7172e86f
>   which is an INTERNAL symbol in the COMMON-LISP-USER package
>    0 type ---------> Bit field: #x07
>    1 flags --------> Bit field: #x00
>    2 package ------> The COMMON-LISP-USER package
>    3 value --------> ..unbound..
>    4 function -----> ..funbound..
>    5 hash ---------> Bit field: #x6f5750
>    6 name ---------> A simple-string (1) "A"
>    7 plist --------> The symbol NIL
> [1i] CL-USER(2): :i set value 10
> A NEW The symbol A @ #x7172e86f
>   which is an INTERNAL symbol in the COMMON-LISP-USER package
>    0 type ---------> Bit field: #x07
>    1 flags --------> Bit field: #x00
>    2 package ------> The COMMON-LISP-USER package
>    3 value --------> fixnum 10 [#x00000028]
>    4 function -----> ..funbound..
>    5 hash ---------> Bit field: #x6f5750
>    6 name ---------> A simple-string (1) "A"
>    7 plist --------> The symbol NIL
> [1i] CL-USER(3): a
> 10
> [1i] CL-USER(4): :in #'print-object
> A TENURED #<STANDARD-GENERIC-FUNCTION PRINT-OBJECT>
>   lambda-list: ((EXCL::X SYS::AUGMENTABLE-ENVIRONMENT-BASE) STREAM)
>    0 Class --------> #<MOP:FUNCALLABLE-STANDARD-CLASS
>                        STANDARD-GENERIC-FUNCTION>
>    1 PLIST --------> The symbol NIL
>    2 FLAGS --------> fixnum 1 [#x00000004]
>    3 NAME ---------> The symbol PRINT-OBJECT
>    4 METHODS ------> (# # # # # # # # # # ...), a proper list with 64
> elements
>    5 METHOD-CLASS -> #<STANDARD-CLASS STANDARD-METHOD>
>    6 METHOD-COMBINATION -> #<EXCL::STANDARD-METHOD-COMBINATION @
>                              #x7111a91a>
>    7 ARG-INFO -----> simple T vector (7) = #(EXCL::ARG-INFO T ...)
> [2i] CL-USER(5): :i raw
> A TENURED #<STANDARD-GENERIC-FUNCTION PRINT-OBJECT>
>   lambda-list: ((EXCL::X SYS::AUGMENTABLE-ENVIRONMENT-BASE) STREAM)
>    0 excl-type ----> Bit field: #x08
>    1 flags --------> Bit field: #x89
>    2 start --------> Bit field: #x0196982c
>    3 hash ---------> Bit field: #x0000242c
>    4 symdef -------> The symbol PRINT-OBJECT
>    5 code ---------> short simple CODE vector (7) = #(30347 65298
> 62054 ...)
>    6 formals ------> ((EXCL::X ...) ...), a proper list with 2
> elements
>    7 disc-type ----> The symbol :CACHING
>    8 disc-cache ---> simple T vector (32) = #(0 NIL ...)
>    9 disc-result --> The symbol NIL
>   10 fin-fun ------> #<Closure (:DISCRIMINATOR
>                                 (:CACHING (CLASS T) NIL))
>                        @ #x71738d1a>
>   11 wrapper ------> simple T vector (7) = #(5098920 T ...)
>   12 slots --------> simple T vector (7) = #(NIL 1 PRINT-OBJECT ...)
> [2i] CL-USER(6): :i set 6 '(bogus)
> A TENURED #<STANDARD-GENERIC-FUNCTION PRINT-OBJECT>
>   lambda-list: (BOGUS)
>    0 excl-type ----> Bit field: #x08
>    1 flags --------> Bit field: #x89
>    2 start --------> Bit field: #x0196982c
>    3 hash ---------> Bit field: #x0000242c
>    4 symdef -------> The symbol PRINT-OBJECT
>    5 code ---------> short simple CODE vector (7) = #(30347 65298
> 62054 ...)
>    6 formals ------> (BOGUS), a proper list with 1 element
>    7 disc-type ----> The symbol :CACHING
>    8 disc-cache ---> simple T vector (32) = #(0 NIL ...)
>    9 disc-result --> The symbol NIL
>   10 fin-fun ------> #<Closure (:DISCRIMINATOR
>                                 (:CACHING (CLASS T) NIL))
>                        @ #x7158f45a>
>   11 wrapper ------> simple T vector (7) = #(5098920 T ...)
>   12 slots --------> simple T vector (7) = #(NIL 1 PRINT-OBJECT ...)
> [2i] CL-USER(7): (arglist 'print-object)
> (BOGUS)
> T
> [2i] CL-USER(8):
>
> Enjoy.
>
> Duane

Thanks to all.