Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
how to call specific method of generic function
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  8 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Tamas Papp  
View profile  
 More options Apr 14 2012, 8:58 am
Newsgroups: comp.lang.lisp
From: Tamas Papp <tkp...@gmail.com>
Date: Sat, 14 Apr 2012 12:58:23 +0000 (UTC)
Local: Sat, Apr 14 2012 8:58 am
Subject: how to call specific method of generic function
Hi,

I am solving a problem using a numerical method, but for a specific
case an analytical solution exists.  The solution will be implemented
by a generic function.  I thought it would be nice to test my method
by comparing the analytical and numerical solutions for the specific
case, but I for that I need to force the numerical solution when CLOS
would dispatch to the analytical one.

Example:

(defgeneric addto5 (arg)
  (:documentation "self-contained-example, dumbed down")
  (:method (arg)
    ;; general
    (+ 5 arg))
  (:method ((arg (eql 0)))
    ;; specific
    5))

I want to test something like

(= (addto5 0)  ; want to call general, but don't know how
   (addto5 0)) ; specific

I can, of course, always write the numerical and the analytical
implementations as plain vanilla functions and have the generic
function call those, but it would be so nice to have a simple code in
the main library (at the price of more complex code in the unit tests
-- I imagine that I would need to use MOP for this?)

Best,

Tamas


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Costanza  
View profile  
 More options Apr 14 2012, 11:03 am
Newsgroups: comp.lang.lisp
From: Pascal Costanza <p...@p-cos.net>
Date: Sat, 14 Apr 2012 17:03:26 +0200
Local: Sat, Apr 14 2012 11:03 am
Subject: Re: how to call specific method of generic function
On 14/04/2012 14:58, Tamas Papp wrote:

When you have the MOP, you can use generic-function-methods to obtain
the methods that are associated with the generic function:

 > (defgeneric addto5 (arg)
     (:documentation "self-contained-example, dumbed down")
     (:method (arg)
       ;; general
       (+ 5 arg))
     (:method ((arg (eql 0)))
       ;; specific
       5))
#<STANDARD-GENERIC-FUNCTION ADDTO5 21B6E25A>

 > (generic-function-methods #'addto5)
(#<STANDARD-METHOD ADDTO5 NIL (T) 21B6E0AF>
  #<STANDARD-METHOD ADDTO5 NIL ((EQL 0)) 21B6E14B>)

method-function reveals the method bodies:

 > (mapcar #'method-function *)
(#<interpreted function (METHOD ADDTO5 (T)) 21B5D0DA>
  #<interpreted function (METHOD ADDTO5 ((EQL 0))) 21B6E64A>)

...and those functions can be funcalled:

 > (mapcar (lambda (f) (funcall f 0)) *)
(5 5)

Note, however, that Common Lisp implementations differ in what argument
lists method functions accept. The above example was in LispWorks, which
does not conform to the CLOS MOP specification here. The correct
invocation should be this:

 > (mapcar (lambda (f) (funcall f '(0) '())) *)

I strongly believe this should work in SBCL, for example, but I haven't
tested it.

[According to the CLOS MOP, a method function receives the list of
arguments plus a list of "next" methods that call-next-method can invoke.]

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
The views expressed are my own, and not those of my employer.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mirko Vukovic  
View profile  
 More options Apr 15 2012, 4:43 pm
Newsgroups: comp.lang.lisp
From: Mirko Vukovic <mirko.vuko...@gmail.com>
Date: Sun, 15 Apr 2012 13:43:53 -0700 (PDT)
Local: Sun, Apr 15 2012 4:43 pm
Subject: Re: how to call specific method of generic function

This is only tangentially related to your question, but it may help (Pascal's answer definitely enlightened me).

I also have multiple methods calculating the same thing, using different models or approximations.

For that I use a combination of methods, special variables,  and functions.  Using your example, I would have addto5% method, *addto5-default-method* special variable and addto5 function:

(defgeneric addto5% (method arg)
  (:documentation "Add 5, using specified METHOD")
  (:method (method arg)
    (declare (ignore method))
    ;; general
    (+ 5 arg))
  (:method ((method (eql :binary)) arg)
    (declare (ignore method))
    (+ arg #b101)))

(defparameter *addto5-default-method* :binary
  "Specify default addto5 method.  Valid values are NIL or :BINARY")

(defun addto5 (arg)
   (addto5% *addto5-default-method* arg))

At the user level, I use addto5 & *addto5-default-method*.  But internally, I may use addto5%.

It is a bit clunky, but with a macro, one can hide some of the repetitive details.

Mirko


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Costanza  
View profile  
 More options Apr 15 2012, 7:04 pm
Newsgroups: comp.lang.lisp
From: Pascal Costanza <p...@p-cos.net>
Date: Mon, 16 Apr 2012 01:04:49 +0200
Local: Sun, Apr 15 2012 7:04 pm
Subject: Re: how to call specific method of generic function
On 15/04/2012 22:43, Mirko Vukovic wrote:

This is an example which can be more cleanly expressed with ContextL:

 > (define-layered-function addto5 (arg))
#<LAYERED-FUNCTION ADDTO5 200A19E2>

 > (define-layered-method addto5 (arg)
     (+ 5 arg))
#<LAYERED-METHOD ADDTO5 T NIL (#<BUILT-IN-CLASS T 20A8F65F>) 21E05533>

 > (deflayer float)
#<STANDARD-LAYER-CLASS FLOAT 200A7E23>

 > (define-layered-method addto5 :in-layer float (arg)
     (+ arg 5.0))
#<LAYERED-METHOD ADDTO5 #<LAYER FLOAT 200FEB67> NIL (#<BUILT-IN-CLASS T
20A8F65F>) 200FF327>

 > (addto5 6)
11

 > (with-active-layers (float)
     (addto5 6))
11.0

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
The views expressed are my own, and not those of my employer.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
tar...@google.com  
View profile  
 More options Apr 16 2012, 9:25 pm
Newsgroups: comp.lang.lisp
From: tar...@google.com
Date: Mon, 16 Apr 2012 18:25:14 -0700 (PDT)
Local: Mon, Apr 16 2012 9:25 pm
Subject: Re: how to call specific method of generic function

Well, if you want something general to use for the case where all of the methods up the generalization hierarchy are supposed to return the same value, you could build this out of COMPUTE-APPLICABLE-METHODS, FUNCALL and the MOP accessor METHOD-FUNCTION.  This version works with SBCL. You will need to adjust the package name on METHOD-FUNCTION for other lisps.

(defun check-all-methods (function &rest args)
  (setq function (coerce function 'function))
  (let ((all-methods (compute-applicable-methods function args)))
    (reduce #'=
            (loop for (method . next-methods) on all-methods by #'cdr
               collect (funcall (sb-mop:method-function method)
                                args
                                next-methods)))))


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Nicolas Neuss  
View profile  
 More options Apr 17 2012, 2:11 am
Newsgroups: comp.lang.lisp
From: Nicolas Neuss <lastn...@scipolis.de>
Date: Tue, 17 Apr 2012 08:11:20 +0200
Local: Tues, Apr 17 2012 2:11 am
Subject: Re: how to call specific method of generic function

tar...@google.com writes:
> (defun check-all-methods (function &rest args)
>   (setq function (coerce function 'function))
>   (let ((all-methods (compute-applicable-methods function args)))
>     (reduce #'=

Good idea, but you probably want APPLY here.

>        (loop for (method . next-methods) on all-methods by #'cdr
>           collect (funcall (sb-mop:method-function method)
>                            args
>                            next-methods)))))

Nicolas

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
tar...@google.com  
View profile  
 More options Apr 17 2012, 8:13 pm
Newsgroups: comp.lang.lisp
From: tar...@google.com
Date: Tue, 17 Apr 2012 17:13:57 -0700 (PDT)
Local: Tues, Apr 17 2012 8:13 pm
Subject: Re: how to call specific method of generic function

On Monday, April 16, 2012 11:11:20 PM UTC-7, Nicolas Neuss wrote:
> tar...@google.com writes:

> > (defun check-all-methods (function &rest args)
> >   (setq function (coerce function 'function))
> >   (let ((all-methods (compute-applicable-methods function args)))
> >     (reduce #'=

> Good idea, but you probably want APPLY here.

Correct. I spaced out and was trying to avoid the arglist length. But that doesn't work here since #'= returns T or NIL and not a number.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
nikode...@random-state.net  
View profile  
 More options Apr 18 2012, 6:57 am
Newsgroups: comp.lang.lisp
From: nikode...@random-state.net
Date: Wed, 18 Apr 2012 03:57:59 -0700 (PDT)
Local: Wed, Apr 18 2012 6:57 am
Subject: Re: how to call specific method of generic function

On Saturday, 14 April 2012 15:58:23 UTC+3, Tamas  wrote:
> I want to test something like

> (= (addto5 0)  ; want to call general, but don't know how
>    (addto5 0)) ; specific

> I can, of course, always write the numerical and the analytical
> implementations as plain vanilla functions and have the generic
> function call those, but it would be so nice to have a simple code in
> the main library (at the price of more complex code in the unit tests
> -- I imagine that I would need to use MOP for this?)

The way I would probably do this is via ADD-METHOD/REMOVE-METHOD:

(defmacro without-specialized-methods ((fname) &body body)
  `(call-without-specialized-methods
    (lambda () ,@body)
    #',fname))

(defun call-without-specialized-methods (thunk gf)
  (let ((class-t (find-class t))
        (removed nil))
    (unwind-protect
         (progn
           (dolist (m (sb-mop:generic-function-methods gf))
             (unless (every (lambda (s)
                              (eq s class-t))
                            (sb-mop:method-specializers m))
               (push m removed)
               (sb-mop:remove-method gf m)))
           (funcall thunk))
      (dolist (m removed)
        (sb-mop:add-method gf m)))))

Completely untested. Same approach could be used to write

  (without-method (spec1 spec2)
     ...body...)

removing the method specialized on SPEC1 and SPEC2 for BODY, etc.

This /is/ a bit heavy-handed, but you are testing the internals of your own code, so...

I also suspect that the bits of MOPery required here are extremely portable. I would expect no trouble just using CLOSER-MOP for this. (I would expect no trouble using CLOSER-MOP for most anything, really, but simple and straightforward things like this should be completely trouble-free.)

Cheers,

 -- nikodemus


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »