[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

attaching context to a function

kamen-no-spam

12/10/2015 10:22:00 AM

Hi,

I'm in the following situation:

(defpackage lib-pack
(:use #:cl)
(:export #:callback #:publish))
(in-package :lib-pack)
(let ((fun))
(defun publish (f) (setq fun f))
(defun callback (arg) (funcall fun (find-symbol arg :cl-user))))

(defpackage p1
(:use #:cl #:lib-pack))
(in-package :p1)
(defclass c1 () ())
(defun bar () (print "hi"))
(publish
(function (lambda (arg)
(bar)
(make-instance arg))))
(callback "C1")


lib-pack is a library someone wrote.

I have no idea why `callback' searches for symbols in CL-USER. I haven't
seen it in the code, I just see the error. `callback' is not called
directly but as a result of some event. The event results in parameters
like "C1".

Apparently changing the lib or polluting cl-user package are not viable
options.

Question: Can I somehow send "the context" with the lambda expression?
(1) is it possible; (2) how?



Thanks in advance,

--
Kamen
3 Answers

Pascal J. Bourguignon

12/10/2015 1:29:00 PM

0

kamen-no-spam@gmail.com writes:

> Hi,
>
> I'm in the following situation:
>
> (defpackage lib-pack
> (:use #:cl)
> (:export #:callback #:publish))
> (in-package :lib-pack)
> (let ((fun))
> (defun publish (f) (setq fun f))
> (defun callback (arg) (funcall fun (find-symbol arg :cl-user))))
>
> (defpackage p1
> (:use #:cl #:lib-pack))
> (in-package :p1)
> (defclass c1 () ())
> (defun bar () (print "hi"))
> (publish
> (function (lambda (arg)
> (bar)
> (make-instance arg))))
> (callback "C1")
>
>
> lib-pack is a library someone wrote.
>
> I have no idea why `callback' searches for symbols in CL-USER. I haven't
> seen it in the code, I just see the error. `callback' is not called
> directly but as a result of some event. The event results in parameters
> like "C1".
>
> Apparently changing the lib or polluting cl-user package are not viable
> options.

Polluting the CL-USER package was expected by your library. Are you
sure you cannot import the few class names you have into CL-USER?

(import 'p1::c1 :cl-user)


> Question: Can I somehow send "the context" with the lambda expression?
> (1) is it possible; (2) how?

The library uses find-symbol, this is a problem or your salvation.

It's a problem because even if you wanted to avoid importing your class
names in CL-USER, you'd still have to intern symbols of the same names,
or other symbols with a map to your class names, in the cl-user
package. Granted, since CL-USER MAY already have the symbols of CL
present, you could map those to your class names. But actually, there's
no guarantee that the symbols in CL-USER actually come from CL or any
other package, or that there are enough symbols in CL-USER to match your
number of classes. There's no guarantees. But let's say that the
following has good chances of working:


(defparameter *my-classes* '(c1 c2 c3 c3))
(defparameter *cl-user-symbols* (let ((l '()))
(do-symbols (s :cl-user l)
(push s l))))
(defparameter *my-classes-map* (make-hash-table))
(map nil (lambda (n c) (setf (gethash n *my-classes-map*) c))
*cl-user-symbols* *my-classes*)

(publish (lambda (name)
(bar)
(make-instance (gethash *my-classes-map* name))))
(callback (first *cl-user-symbols*))

Yeah, it's dumb. Almost as dumb as the following solution, thanks to
the salvation of find-symbol, which returns nil when the symbol is not
found. Said otherwise, you can just ignore the callback parameter, and
pass the class name in a global variable:

(defvar *class-name* nil)
(publish (lambda (name)
(declare (ignore name))
(bar)
(make-instance *class-name*)))
(let ((*class-name* 'c1))
(call-back "IGNORE"))

If you don't like the dynamic binding, of course, you can enclose it:

(let ((class-name nil))
(defun set-class-name (name) (setf class-name name))
(defun fun (name)
(declare (ignore name))
(bar)
(make-instance class-name)))

(publish (function fun))

(progn (set-class-name 'c1)
(call-back "IGNORE"))

(progn (set-class-name 'c2)
(call-back "IGNORE"))

But in presence of multiple threads, you might still prefer the dynamic
binding, since each threads gets its own set of special variables,
normally. Otherwise, you will need to add a lock around the calls to
set-class-name and call-back.


Finally, I would have you notice that:

1- apparently you have the source code of that library, so why the fuck
don't you edit it to do what it should do?

2- even if you didn't have the source code, and had infered the behavior
described above from the documentation or reverse engineering, you
can still patch the library after it is loaded, by merely redefining
the deficient callback function.

--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

kamen-no-spam

12/13/2015 10:46:00 AM

0

"Pascal J. Bourguignon" <pjb@informatimago.com> writes:

> Polluting the CL-USER package was expected by your library. Are you
> sure you cannot import the few class names you have into CL-USER?
>
> (import 'p1::c1 :cl-user)

First of all thanks a lot for your reply. I thought the news server
didn't like my posts in the group so nobody was seeing them.

> The library uses find-symbol, this is a problem or your salvation.

Actually I'm not sure about that. I only have an error message saying
that it can't find the symbol in CL-USER. Perhaps it searches elsewhere
before that.

> It's a problem because even if you wanted to avoid importing your class
....

Very "out of the box" :-D

> Finally, I would have you notice that:
>
> 1- apparently you have the source code of that library, so why the
> fuck don't you edit it to do what it should do?

What puzzles me is that with other classes the lib works fine - I only
have the problem with a class named NODE. I'm yet to investigate it.

> 2- even if you didn't have the source code, and had infered the
> behavior described above from the documentation or reverse
> engineering, you can still patch the library after it is loaded, by
> merely redefining the deficient callback function.

The power of Lisp :)


Anyway it is always good to discuss with somebody and it reminded me how
much I enjoy this group.

Pascal J. Bourguignon

12/13/2015 11:00:00 AM

0

kamen-no-spam@gmail.com writes:

> "Pascal J. Bourguignon" <pjb@informatimago.com> writes:
>
>> Polluting the CL-USER package was expected by your library. Are you
>> sure you cannot import the few class names you have into CL-USER?
>>
>> (import 'p1::c1 :cl-user)
>
> First of all thanks a lot for your reply. I thought the news server
> didn't like my posts in the group so nobody was seeing them.
>
>> The library uses find-symbol, this is a problem or your salvation.
>
> Actually I'm not sure about that. I only have an error message saying
> that it can't find the symbol in CL-USER. Perhaps it searches elsewhere
> before that.
>
>> It's a problem because even if you wanted to avoid importing your class
> ...
>
> Very "out of the box" :-D
>
>> Finally, I would have you notice that:
>>
>> 1- apparently you have the source code of that library, so why the
>> fuck don't you edit it to do what it should do?
>
> What puzzles me is that with other classes the lib works fine - I only
> have the problem with a class named NODE. I'm yet to investigate it.
>
>> 2- even if you didn't have the source code, and had infered the
>> behavior described above from the documentation or reverse
>> engineering, you can still patch the library after it is loaded, by
>> merely redefining the deficient callback function.
>
> The power of Lisp :)
>
>
> Anyway it is always good to discuss with somebody and it reminded me how
> much I enjoy this group.

Remember, when you use slime and sldb, you only have to type v on a
frame line to jump to the source of the corresponding function. Doing
that successively on the frames in sldb (typing n to go to the next
frame, n v n v n v â?¦) you will see the source of each caller function.

This will allow to find very soon what and where is done to break on
this error, and help you determine either if you need to patch the
library, or the way you call it.


--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk