From: Onay Urfalioglu
Subject: generic programming + Lisp
Date: 
Message-ID: <430f95c8$0$24159$9b4e6d93@newsread4.arcor-online.net>
consider source code which may not be modified:

(defun f (y)
    ...
    (setf x (random y))
    ...)

Having an "interval" type aka 

(defclass interval ()
   left right)

there is a reasonable need for a 

(random interval-instance) -> (+ left (random right)).
 
Unfortunately, function f cannot be "reused" in this example, since
random does not accept or even know of the interval type. Shadowing also
does not work, since the labda list of the random function makes it non
"generalizable", in the sense of shadowing it and wrapping by generic
methods. 
As an example, the function abs is "generalizable":

(shadow 'abs)
(defmethod abs ((x t)) (cl:abs x)) ;-> |scalar|
(defmethod abs ((x vector)) ...))  ;-> |vector|

If i did not miss something, the generic OOP paradigm and Lisp collide here.
To me, this is a major downside of Lisp, which is supposed to be a generic
language.

regards
-- 
(+::+) oni (+::+)
(I already try to be as amusing as possible, my master!)

From: Barry Margolin
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <barmar-C878F6.18433526082005@comcast.dca.giganews.com>
In article <·························@newsread4.arcor-online.net>,
 Onay Urfalioglu <·····@gmx.net> wrote:

> consider source code which may not be modified:
> 
> (defun f (y)
>     ...
>     (setf x (random y))
>     ...)
> 
> Having an "interval" type aka 
> 
> (defclass interval ()
>    left right)
> 
> there is a reasonable need for a 
> 
> (random interval-instance) -> (+ left (random right)).
>  
> Unfortunately, function f cannot be "reused" in this example, since
> random does not accept or even know of the interval type. Shadowing also
> does not work, since the labda list of the random function makes it non
> "generalizable", in the sense of shadowing it and wrapping by generic
> methods. 
> As an example, the function abs is "generalizable":
> 
> (shadow 'abs)
> (defmethod abs ((x t)) (cl:abs x)) ;-> |scalar|
> (defmethod abs ((x vector)) ...))  ;-> |vector|

Why do you have to use the same name as the standard function?

(defmethod my-random ((x t)) (random x))
(defmethod my-random ((x interval))
  (+ (interval-left x)
     (my-random (- (interval-right x) (interval-left x)))))

The shadowing technique doesn't really make the built-in function 
generic, since any programs that don't use your package won't call your 
generic function anyway.  So it's mostly just a cosmetic feature for 
your own program, to allow you to use the nice, short names that CL 
grabbed for itself.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Onay Urfalioglu
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <430f9d7b$0$24153$9b4e6d93@newsread4.arcor-online.net>
Barry Margolin wrote:

> In article <·························@newsread4.arcor-online.net>,
>  Onay Urfalioglu <·····@gmx.net> wrote:
> 
>> consider source code which may not be modified:
>> 
>> (defun f (y)
>>     ...
>>     (setf x (random y))
>>     ...)
>> 
>> Having an "interval" type aka
>> 
>> (defclass interval ()
>>    left right)
>> 
>> there is a reasonable need for a
>> 
>> (random interval-instance) -> (+ left (random right)).
>>  
>> Unfortunately, function f cannot be "reused" in this example, since
>> random does not accept or even know of the interval type. Shadowing also
>> does not work, since the labda list of the random function makes it non
>> "generalizable", in the sense of shadowing it and wrapping by generic
>> methods.
>> As an example, the function abs is "generalizable":
>> 
>> (shadow 'abs)
>> (defmethod abs ((x t)) (cl:abs x)) ;-> |scalar|
>> (defmethod abs ((x vector)) ...))  ;-> |vector|
> 
> Why do you have to use the same name as the standard function?
> 
> (defmethod my-random ((x t)) (random x))
> (defmethod my-random ((x interval))
>   (+ (interval-left x)
>      (my-random (- (interval-right x) (interval-left x)))))
> 
> The shadowing technique doesn't really make the built-in function
> generic, since any programs that don't use your package won't call your
> generic function anyway.  So it's mostly just a cosmetic feature for
> your own program, to allow you to use the nice, short names that CL
> grabbed for itself.
> 

Well, as i stated, the function f is to be reused.

This way, i should clarify my statement:
I am not complaining the Lisp language is not generic, but its standart
library...
-- 
(+::+) oni (+::+)
(I already try to be as amusing as possible, my master!)
From: Barry Margolin
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <barmar-B7D59B.19192126082005@comcast.dca.giganews.com>
In article <·························@newsread4.arcor-online.net>,
 Onay Urfalioglu <·····@gmx.net> wrote:

> I am not complaining the Lisp language is not generic, but its standart
> library...

This is by design.  We didn't want to force OO all the way down into the 
guts of the implementations.  Requiring every built-in function to be 
generic, including real basic operations like CAR/CDR and arithmetic, 
could impose significant performance impact unless lots of declarations 
were used.

To some extent this is also due to history: CLOS was a late addition to 
the language (it wasn't in CLTL1), so it was treated as an add-on.  It's 
not used much in the language itself, it's mostly there for user 
applications.  The only built-in CLOS generic functions I can think of 
are the ones used by CLOS itself and a few high-level utility functions 
(PRINT-OBJECT and DOCUMENTATION).

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Peter Seibel
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <m2vf1sqpto.fsf@gigamonkeys.com>
Onay Urfalioglu <·····@gmx.net> writes:

> consider source code which may not be modified:
>
> (defun f (y)
>     ...
>     (setf x (random y))
>     ...)
>
> Having an "interval" type aka 
>
> (defclass interval ()
>    left right)
>
> there is a reasonable need for a 
>
> (random interval-instance) -> (+ left (random right)).
>  
> Unfortunately, function f cannot be "reused" in this example, since
> random does not accept or even know of the interval type. Shadowing
> also does not work, since the labda list of the random function
> makes it non "generalizable", in the sense of shadowing it and
> wrapping by generic methods.
>
> As an example, the function abs is "generalizable":
>
> (shadow 'abs)
> (defmethod abs ((x t)) (cl:abs x)) ;-> |scalar|
> (defmethod abs ((x vector)) ...))  ;-> |vector|

What's wrong with this:

  (shadow 'random)

  (defgeneric random (x &optional random-state)

  (defmethod random ((x t) &optional (random-state *random-state*))
    (cl:random x random-state))

  (defclass interval ()
    ((left :initarg :left :accessor left)
     (right :initarg :right :accessor right)))

  (defmethod random ((x interval) &optional (random-state *random-state*))
    (with-slots (left right) x
      (+ left (random (- right left) random-state))))

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Onay Urfalioglu
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <430f9f10$0$2113$9b4e6d93@newsread2.arcor-online.net>
Peter Seibel wrote:

> Onay Urfalioglu <·····@gmx.net> writes:
> 
>> consider source code which may not be modified:
>>
>> (defun f (y)
>>     ...
>>     (setf x (random y))
>>     ...)
>>
>> Having an "interval" type aka
>>
>> (defclass interval ()
>>    left right)
>>
>> there is a reasonable need for a
>>
>> (random interval-instance) -> (+ left (random right)).
>>  
>> Unfortunately, function f cannot be "reused" in this example, since
>> random does not accept or even know of the interval type. Shadowing
>> also does not work, since the labda list of the random function
>> makes it non "generalizable", in the sense of shadowing it and
>> wrapping by generic methods.
>>
>> As an example, the function abs is "generalizable":
>>
>> (shadow 'abs)
>> (defmethod abs ((x t)) (cl:abs x)) ;-> |scalar|
>> (defmethod abs ((x vector)) ...))  ;-> |vector|
> 
> What's wrong with this:
> 
>   (shadow 'random)
> 
>   (defgeneric random (x &optional random-state)
> 
>   (defmethod random ((x t) &optional (random-state *random-state*))
>     (cl:random x random-state))
> 
>   (defclass interval ()
>     ((left :initarg :left :accessor left)
>      (right :initarg :right :accessor right)))
> 
>   (defmethod random ((x interval) &optional (random-state *random-state*))
>     (with-slots (left right) x
>       (+ left (random (- right left) random-state))))
> 
> -Peter
> 

Oh, i see ! Apparantly, i misunderstood the sentence 
"You cannot specialize on &optional , &rest or &key variables. I.e. same
number of required args. Steele calls this "lambda list congruence"."
from http://www.apl.jhu.edu/~hall/AI-Programming/CLOS.html

Thank You!
-- 
(+::+) oni (+::+)
(I already try to be as amusing as possible, my master!)
From: Nathan Baum
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <deoffe$79d$1@newsg3.svr.pol.co.uk>
Onay Urfalioglu wrote:
> 
> Oh, i see ! Apparantly, i misunderstood the sentence 
> "You cannot specialize on &optional , &rest or &key variables. I.e. same
> number of required args. Steele calls this "lambda list congruence"."
> from http://www.apl.jhu.edu/~hall/AI-Programming/CLOS.html
> 
It means you cannot _specialize_ on such variables, not that such 
variables can't appear in a lambda list.

If you _could_ specialise on an &optional, &rest or &key parameter, 
which method should be selected when that parameter is not present?

This is the same thing seen in C++, for example:

   bool foo (int x, float y = 0.0);
   bool foo (int x, const char *y = "");
   bool bar = foo(42);

This is an error because the call to 'foo' is ambiguous.

In CLOS, the error is avoided by simply not allowing one to specialise 
upon such parameters.
From: Marco Baringer
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <m264trd2nx.fsf@soma.local>
Nathan Baum <···········@btinternet.com> writes:

> Onay Urfalioglu wrote:
>> Oh, i see ! Apparantly, i misunderstood the sentence "You cannot
>> specialize on &optional , &rest or &key variables. I.e. same
>> number of required args. Steele calls this "lambda list congruence"."
>> from http://www.apl.jhu.edu/~hall/AI-Programming/CLOS.html
>> 
> It means you cannot _specialize_ on such variables, not that such
> variables can't appear in a lambda list.
>
> If you _could_ specialise on an &optional, &rest or &key parameter,
> which method should be selected when that parameter is not present?

&rest is slighly more complicated, but specializing on &optional and
&key is easy:

(defun generic-public (required &optional optional &key key)
  (generic-internal required optional key))

(defgeneric generic-internal (required optional key))

(defmethod generic-internal ...)

...

-- 
-Marco
Ring the bells that still can ring.
Forget the perfect offering.
There is a crack in everything.
That's how the light gets in.
	-Leonard Cohen
From: Christopher C. Stacy
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <uirxskzib.fsf@news.dtpq.com>
Onay Urfalioglu <·····@gmx.net> writes:

> consider source code which may not be modified:
> 
> (defun f (y)
>     ...
>     (setf x (random y))
>     ...)
> 
> Having an "interval" type aka 
> 
> (defclass interval ()
>    left right)
> 
> there is a reasonable need for a 
> 
> (random interval-instance) -> (+ left (random right)).
>  

> Unfortunately, function f cannot be "reused" in this example,
> since random does not accept or even know of the interval type.
> Shadowing also does not work, since the labda list of the
> random function makes it non "generalizable", in the sense
> of shadowing it and wrapping by generic methods.

What do you think is unusual about the lambda list 
of RANDOM, and in what way does shadowing "not work"?

(shadow 'random)

(defgeneric random (arg &optional state))

(defmethod random ((arg t) &optional state)
  (if state (cl:random arg state) (cl:random arg)))

(defmethod random ((interval interval) &optional state)
  (with-slots (left right) interval
   (+ left (if state (cl:random right state) (cl:random right)))))


You shouldn't randomly shadow things, though.
From: Onay Urfalioglu
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <430f96c3$0$24148$9b4e6d93@newsread4.arcor-online.net>
Onay Urfalioglu wrote:


> (random interval-instance) -> (+ left (random right)).

i mean of course 
(random interval-instance) -> (+ left (random (- right left))).

regards

-- 
(+::+) oni (+::+)
(I already try to be as amusing as possible, my master!)
From: Ulrich Hobelmann
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <3n9kdpFh0v8U1@individual.net>
Onay Urfalioglu wrote:
> consider source code which may not be modified:
> 
> (defun f (y)
>     ...
>     (setf x (random y))
>     ...)
> 
> Having an "interval" type aka 
> 
> (defclass interval ()
>    left right)
> 
> there is a reasonable need for a 
> 
> (random interval-instance) -> (+ left (random right)).

Why don't you defgeneric the random function?  (ok, since it's 
predefined that means you'd have to make your own package and shadow it)

Make random for ints call the original / some random function; make 
random for intervals call the new thing.

> Unfortunately, function f cannot be "reused" in this example, since
> random does not accept or even know of the interval type. Shadowing also
> does not work, since the labda list of the random function makes it non
> "generalizable", in the sense of shadowing it and wrapping by generic
> methods. 
> As an example, the function abs is "generalizable":
> 
> (shadow 'abs)
> (defmethod abs ((x t)) (cl:abs x)) ;-> |scalar|
> (defmethod abs ((x vector)) ...))  ;-> |vector|

(defmethod random ((n interval)) ...) ; for intervals, dito for numbers

shadow cl:random, then later call it.

> If i did not miss something, the generic OOP paradigm and Lisp collide here.
> To me, this is a major downside of Lisp, which is supposed to be a generic
> language.

I totally don't understand the difference between your abs example and 
the random thing you're trying to achieve...  Well, it's getting late here.

-- 
I believe in Karma.  That means I can do bad things to people
all day long and I assume they deserve it.
	Dogbert
From: Onay Urfalioglu
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <430f9ce9$0$2114$9b4e6d93@newsread2.arcor-online.net>
Ulrich Hobelmann wrote:

> Onay Urfalioglu wrote:
>> consider source code which may not be modified:
>> 
>> (defun f (y)
>>     ...
>>     (setf x (random y))
>>     ...)
>> 
>> Having an "interval" type aka
>> 
>> (defclass interval ()
>>    left right)
>> 
>> there is a reasonable need for a
>> 
>> (random interval-instance) -> (+ left (random right)).
> 
> Why don't you defgeneric the random function?  (ok, since it's
> predefined that means you'd have to make your own package and shadow it)
> 
> Make random for ints call the original / some random function; make
> random for intervals call the new thing.

The labda list of random is 

random limit &optional random-state

as i understand, optional parameters cannot be captured in generic
defmethods

>> Unfortunately, function f cannot be "reused" in this example, since
>> random does not accept or even know of the interval type. Shadowing also
>> does not work, since the labda list of the random function makes it non
>> "generalizable", in the sense of shadowing it and wrapping by generic
>> methods.
>> As an example, the function abs is "generalizable":
>> 
>> (shadow 'abs)
>> (defmethod abs ((x t)) (cl:abs x)) ;-> |scalar|
>> (defmethod abs ((x vector)) ...))  ;-> |vector|
> 
> (defmethod random ((n interval)) ...) ; for intervals, dito for numbers
> 
> shadow cl:random, then later call it.
> 
>> If i did not miss something, the generic OOP paradigm and Lisp collide
>> here. To me, this is a major downside of Lisp, which is supposed to be a
>> generic language.
> 
> I totally don't understand the difference between your abs example and
> the random thing you're trying to achieve...  Well, it's getting late
> here.

yep, so gets here 00:50 ;-) 


-- 
(+::+) oni (+::+)
(I already try to be as amusing as possible, my master!)
From: jayessay
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <m3hddb56is.fsf@rigel.goldenthreadtech.com>
Onay Urfalioglu <·····@gmx.net> writes:

> The labda list of random is 
> 
> random limit &optional random-state
> 
> as i understand, optional parameters cannot be captured in generic
> defmethods

I think you're confused.  Example:


(defpackage "TESTING")

(in-package "TESTING")

(shadow 'random) ==> t

(defgeneric random ((x t) &optional y))
  ==> #<standard-generic-function random>

(defmethod random ((x integer) &optional (y 11))
  (+ (cl:random x) y))
  ==> #<standard-method random (integer)>

(random 10)  ==> 11
(random 10)  ==> 12
(random 10 17) ==> 23
(random 10 17) ==> 18


When you shadow the cl:random you are free to create a new random
which maybe generic and totally different in signature, because, well,
it's totally different from the cl:random.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Matthew D Swank
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <pan.2005.08.28.16.14.32.822491@c.net>
On Sat, 27 Aug 2005 19:01:15 -0400, jayessay wrote:


> 
> When you shadow the cl:random you are free to create a new random
> which maybe generic and totally different in signature, because, well,
> it's totally different from the cl:random.
> 
> 
> /Jon

Yes, but it is generally desirable to keep the same signature if you can
in order to effectively extend the language: old ansi-cl code works fine
along side the new stuff.

For example, frequently funcallable instances are not well supported under
some lisps, so I have the following mixin/generic functions:

(defpackage :util
  (:use :common-lisp)
  (:shadow :apply :funcall)
  (:export #:apply #:funcall #:funcallable ))

(in-package :util)


;;yes funcallable instances should work, but
;;support is sketchy so:
(defgeneric apply (function arg &rest arguments)
  ;;preprocesses the arg list: if an implementor wants to see the 
  ;;original arglist she'll need to implement a more specialized 
  ;;around method 
  (:method :around (function arg &rest arguments)
           (labels ((normalize-args (arguments)
                      (let ((rest (cdr arguments)))
                        (typecase rest
                          (null (car arguments))
                          (cons (cons (car arguments)
                                      (normalize-args rest)))))))
             (call-next-method function 
                               (if (null arguments) 
                                   arg 
                                 (cons arg (normalize-args arguments))))))
  (:method (function arg &rest arguments)
           (declare (ignore arguments))
           (common-lisp:apply function arg)))

;;;mmm...mop
;;;though i can't seem to make this work in sbcl
#+:openmcl
(progn
  ;;a slight speed bum, this completely hijacks the method dispatch
  ;;to directly call primitive #'apply _as_ the method body
  (defmethod apply :around ((function function) arg &rest arguments)
    (declare (ignorable function arg arguments))
    'dummy)
  (setf (openmcl-mop:method-function 
         (find-method #'apply 
                      '(:around) 
                      (mapcar #'find-class '(function t))))
        #'common-lisp:apply))

(defun funcall (function &rest arguments)
  (apply function arguments))

;;my first mixin :)
(defclass funcallable ()
  ((func-object
    :initarg   :func-object
    :initform  #'identity
    :accessor  func-object
    :type      (or function funcallable))))

(defmethod apply ((function funcallable) arg &rest arguments)
  (declare (ignore arguments))
  (apply (func-object function) arg))


This allows me to define type aliases like:

;;;;;;;;;;
;;fun: position -> err-monad
;;positional-err is a _function-type_ 
(defclass positional-err (monad funcallable) ())
(defun positional-err (fun)
  (make-instance 'positional-err :func-object fun))


Matt
-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.
From: jayessay
Subject: Re: generic programming + Lisp
Date: 
Message-ID: <m3d5nx60bm.fsf@rigel.goldenthreadtech.com>
Matthew D Swank <·······································@c.net> writes:

> On Sat, 27 Aug 2005 19:01:15 -0400, jayessay wrote:
> 
> 
> > 
> > When you shadow the cl:random you are free to create a new random
> > which maybe generic and totally different in signature, because, well,
> > it's totally different from the cl:random.
> > 
> > 
> > /Jon
> 
> Yes, but it is generally desirable to keep the same signature if you can
> in order to effectively extend the language: old ansi-cl code works fine
> along side the new stuff.

Absolutely.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com