[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.lisp

+,-,*,/ ... are non-generic functions

Taoufik Dachraoui

2/8/2016 2:05:00 PM

Hi

I find that it is unfortunate that + (- * / ...) are non generic functions

I wanted to create a new subtype of number and use it in my programs
without modifying the code, but being unable to define the method +,*,..
on the new type is a stopper.

what do you think about this?

Kind regards
Taoufik
13 Answers

Antsan

2/8/2016 2:21:00 PM

0

Am Montag, 8. Februar 2016 15:04:58 UTC+1 schrieb Taoufik Dachraoui:
> Hi
>
> I find that it is unfortunate that + (- * / ...) are non generic functions
>
> I wanted to create a new subtype of number and use it in my programs
> without modifying the code, but being unable to define the method +,*,..
> on the new type is a stopper.
>
> what do you think about this?
>
> Kind regards
> Taoufik

It's a well-known problem.
To work around this, you can do something like this:

(defpackage #:generic-arithmetic
(:use #:cl)
(:shadow #:+ #:- #:* #:/)
(:export #:+ #:- #:* #:/))

(in-package #:generic-arithmetic)

(defgeneric + (a b) ; because it would be kind of hard to define
; this correctly for &rest parameters - although it
; probably is possible
(:method ((a number)
(b number))
(cl:+ a b)))

and so on.

Taoufik Dachraoui

2/8/2016 3:00:00 PM

0

On Monday, February 8, 2016 at 3:21:36 PM UTC+1, Antsan wrote:
> Am Montag, 8. Februar 2016 15:04:58 UTC+1 schrieb Taoufik Dachraoui:
> > Hi
> >
> > I find that it is unfortunate that + (- * / ...) are non generic functions
> >
> > I wanted to create a new subtype of number and use it in my programs
> > without modifying the code, but being unable to define the method +,*,..
> > on the new type is a stopper.
> >
> > what do you think about this?
> >
> > Kind regards
> > Taoufik
>
> It's a well-known problem.
> To work around this, you can do something like this:
>
> (defpackage #:generic-arithmetic
> (:use #:cl)
> (:shadow #:+ #:- #:* #:/)
> (:export #:+ #:- #:* #:/))
>
> (in-package #:generic-arithmetic)
>
> (defgeneric + (a b) ; because it would be kind of hard to define
> ; this correctly for &rest parameters - although it
> ; probably is possible
> (:method ((a number)
> (b number))
> (cl:+ a b)))
>
> and so on.

Thanks

Is it possible to redefine ccl::%make-ratio, such that (/ 2 3) will call the redefined %make-ratio?

Kind regards
Taoufik

Antsan

2/8/2016 3:03:00 PM

0

Am Montag, 8. Februar 2016 15:21:36 UTC+1 schrieb Antsan:
> Am Montag, 8. Februar 2016 15:04:58 UTC+1 schrieb Taoufik Dachraoui:
> > Hi
> >
> > I find that it is unfortunate that + (- * / ...) are non generic functions
> >
> > I wanted to create a new subtype of number and use it in my programs
> > without modifying the code, but being unable to define the method +,*,..
> > on the new type is a stopper.
> >
> > what do you think about this?
> >
> > Kind regards
> > Taoufik
>
> It's a well-known problem.
> To work around this, you can do something like this:
>
> (defpackage #:generic-arithmetic
> (:use #:cl)
> (:shadow #:+ #:- #:* #:/)
> (:export #:+ #:- #:* #:/))
>
> (in-package #:generic-arithmetic)
>
> (defgeneric + (a b) ; because it would be kind of hard to define
> ; this correctly for &rest parameters - although it
> ; probably is possible
> (:method ((a number)
> (b number))
> (cl:+ a b)))
>
> and so on.

Actually, maybe it would be better to do it like this:

(defun + (&rest nums)
(reduce #'%+ nums :initial-value 0))

(defgeneric %+ (a b)
(:method ((a number)
(b number))
(cl:+ a b)))

Antsan

2/8/2016 3:04:00 PM

0

Am Montag, 8. Februar 2016 15:59:55 UTC+1 schrieb Taoufik Dachraoui:
> On Monday, February 8, 2016 at 3:21:36 PM UTC+1, Antsan wrote:
> > Am Montag, 8. Februar 2016 15:04:58 UTC+1 schrieb Taoufik Dachraoui:
> > > Hi
> > >
> > > I find that it is unfortunate that + (- * / ...) are non generic functions
> > >
> > > I wanted to create a new subtype of number and use it in my programs
> > > without modifying the code, but being unable to define the method +,*,..
> > > on the new type is a stopper.
> > >
> > > what do you think about this?
> > >
> > > Kind regards
> > > Taoufik
> >
> > It's a well-known problem.
> > To work around this, you can do something like this:
> >
> > (defpackage #:generic-arithmetic
> > (:use #:cl)
> > (:shadow #:+ #:- #:* #:/)
> > (:export #:+ #:- #:* #:/))
> >
> > (in-package #:generic-arithmetic)
> >
> > (defgeneric + (a b) ; because it would be kind of hard to define
> > ; this correctly for &rest parameters - although it
> > ; probably is possible
> > (:method ((a number)
> > (b number))
> > (cl:+ a b)))
> >
> > and so on.
>
> Thanks
>
> Is it possible to redefine ccl::%make-ratio, such that (/ 2 3) will call the redefined %make-ratio?
>
> Kind regards
> Taoufik

I have no idea. I don't think so. This wouldn't be portable either way.

Richard Fateman

2/8/2016 3:09:00 PM

0

On 2/8/2016 6:21 AM, Antsan wrote:
> Am Montag, 8. Februar 2016 15:04:58 UTC+1 schrieb Taoufik Dachraoui:
>> Hi
>>
>> I find that it is unfortunate that + (- * / ...) are non generic functions
>>
>> I wanted to create a new subtype of number and use it in my programs
>> without modifying the code, but being unable to define the method +,*,..
>> on the new type is a stopper.
>>
>> what do you think about this?
>>
>> Kind regards
>> Taoufik
>
> It's a well-known problem.
> To work around this, you can do something like this:
>
> (defpackage #:generic-arithmetic
> (:use #:cl)
> (:shadow #:+ #:- #:* #:/)
> (:export #:+ #:- #:* #:/))
>
> (in-package #:generic-arithmetic)
>
> (defgeneric + (a b) ; because it would be kind of hard to define
> ; this correctly for &rest parameters - although it
> ; probably is possible
> (:method ((a number)
> (b number))
> (cl:+ a b)))
>
> and so on.
>

I think that the usual technique would involve defining your
new generic + in terms of a new function called
two-arg-+
etc for all functions that take a variable number of arguments.


Kaz Kylheku

2/15/2016 4:36:00 PM

0

On 2016-02-08, Antsan <thomas.bartscher@gmail.com> wrote:
> Am Montag, 8. Februar 2016 15:04:58 UTC+1 schrieb Taoufik Dachraoui:
>> Hi
>>
>> I find that it is unfortunate that + (- * / ...) are non generic functions
>>
>> I wanted to create a new subtype of number and use it in my programs
>> without modifying the code, but being unable to define the method +,*,..
>> on the new type is a stopper.
>>
>> what do you think about this?
>>
>> Kind regards
>> Taoufik
>
> It's a well-known problem.
> To work around this, you can do something like this:
>
> (defpackage #:generic-arithmetic
> (:use #:cl)
> (:shadow #:+ #:- #:* #:/)
> (:export #:+ #:- #:* #:/))
>
> (in-package #:generic-arithmetic)
>
> (defgeneric + (a b) ; because it would be kind of hard to define
> ; this correctly for &rest parameters - although it
> ; probably is possible

What you do is

(defgeneric bin+ (a b))

(defun + (&rest args)
(reduce #'bin+ args :initial-value 0))

(defmethod bin+ ((a strange-number) (b supernatural-matrix))
...)

That is to say, your redefined + isn't generic at all; it's an ordinary
function that reduces over a binary add which is generic.

Norbert_Paul

2/16/2016 3:30:00 PM

0

Kaz Kylheku wrote:
> On 2016-02-08, Antsan<thomas.bartscher@gmail.com> wrote:
>> Am Montag, 8. Februar 2016 15:04:58 UTC+1 schrieb Taoufik Dachraoui:
>>> Hi
>>>
>>> I find that it is unfortunate that + (- * / ...) are non generic functions
>>>
>>> I wanted to create a new subtype of number and use it in my programs
>>> without modifying the code, but being unable to define the method +,*,..
>>> on the new type is a stopper.
>>>
>>> what do you think about this?
>>>
>>> Kind regards
>>> Taoufik
>>
>> It's a well-known problem.
>> To work around this, you can do something like this:
>>
>> (defpackage #:generic-arithmetic
>> (:use #:cl)
>> (:shadow #:+ #:- #:* #:/)
>> (:export #:+ #:- #:* #:/))
>>
>> (in-package #:generic-arithmetic)
>>
>> (defgeneric + (a b) ; because it would be kind of hard to define
>> ; this correctly for&rest parameters - although it
>> ; probably is possible
>
> What you do is
>
> (defgeneric bin+ (a b))
>
> (defun + (&rest args)
> (reduce #'bin+ args :initial-value 0))
>
> (defmethod bin+ ((a strange-number) (b supernatural-matrix))
> ...)
>
> That is to say, your redefined + isn't generic at all; it's an ordinary
> function that reduces over a binary add which is generic.

I am a bit uncomfortable with ':initial-value 0', because then bin+
is called with the first argument set to 0. With something like

(defun + (&rest args)
(if (null args)
0 ; I don't like this either but it is consistent with the specification
(reduce #'bin+ args)))

you would not have to provide a method for bin+ where a is eql 0
and b is, say, a strange-number or a supernatural-matrix. This would
make definitions like

(defmethod bin+ ((a (eql 0)) (b strange-number)) b)
(defmethod bin+ ((a (eql 0)) (b supernatural-matrix)) b)
...

unnecessary. In particular I do not want to add a vector to a scalar.

Maybe we could introduce some "generic zero"?

(defun + (&rest args)
(let ((purged-args (remove 'generic-zero args)))
(if (null purged-args)
'generic-zero
(reduce #'bin+ purged-args))))

(None of the above code is tested.)

Norbert

Kaz Kylheku

2/16/2016 4:57:00 PM

0

On 2016-02-16, Norbert_Paul <norbertpauls_spambin@yahoo.com> wrote:
> Kaz Kylheku wrote:
>> On 2016-02-08, Antsan<thomas.bartscher@gmail.com> wrote:
>>> Am Montag, 8. Februar 2016 15:04:58 UTC+1 schrieb Taoufik Dachraoui:
>>>> Hi
>>>>
>>>> I find that it is unfortunate that + (- * / ...) are non generic functions
>>>>
>>>> I wanted to create a new subtype of number and use it in my programs
>>>> without modifying the code, but being unable to define the method +,*,..
>>>> on the new type is a stopper.
>>>>
>>>> what do you think about this?
>>>>
>>>> Kind regards
>>>> Taoufik
>>>
>>> It's a well-known problem.
>>> To work around this, you can do something like this:
>>>
>>> (defpackage #:generic-arithmetic
>>> (:use #:cl)
>>> (:shadow #:+ #:- #:* #:/)
>>> (:export #:+ #:- #:* #:/))
>>>
>>> (in-package #:generic-arithmetic)
>>>
>>> (defgeneric + (a b) ; because it would be kind of hard to define
>>> ; this correctly for&rest parameters - although it
>>> ; probably is possible
>>
>> What you do is
>>
>> (defgeneric bin+ (a b))
>>
>> (defun + (&rest args)
>> (reduce #'bin+ args :initial-value 0))
>>
>> (defmethod bin+ ((a strange-number) (b supernatural-matrix))
>> ...)
>>
>> That is to say, your redefined + isn't generic at all; it's an ordinary
>> function that reduces over a binary add which is generic.
>
> I am a bit uncomfortable with ':initial-value 0', because then bin+
> is called with the first argument set to 0. With something like
>
> (defun + (&rest args)
> (if (null args)
> 0 ; I don't like this either but it is consistent with the specification
> (reduce #'bin+ args)))

What reduce could use is a :if-empty keyword arg to provide an
alternative the awkward requirement that the binary function be callable
with no arguments just to produce the value for that case.

(reduce #'bin+ args :if-empty 0)

equivalent to:

(if (zerop (length args)) (reduce #'bin args) 0)

Barry Margolin

2/16/2016 5:00:00 PM

0

In article <20160216080313.644@kylheku.com>,
Kaz Kylheku <330-706-9395@kylheku.com> wrote:

> What reduce could use is a :if-empty keyword arg to provide an
> alternative the awkward requirement that the binary function be callable
> with no arguments just to produce the value for that case.

If the function can't be called with 0 or 1 arguments, how much sense
does it make to reduce it over a list of that length in the first place?

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Norbert_Paul

2/16/2016 5:14:00 PM

0

Kaz Kylheku wrote:
> On 2016-02-16, Norbert_Paul<norbertpauls_spambin@yahoo.com> wrote:
>>
>> I am a bit uncomfortable with ':initial-value 0', because then bin+
>> is called with the first argument set to 0. With something like
>>
>> (defun + (&rest args)
>> (if (null args)
>> 0 ; I don't like this either but it is consistent with the specification
>> (reduce #'bin+ args)))
>
> What reduce could use is a :if-empty keyword arg to provide an
> alternative the awkward requirement that the binary function be callable
> with no arguments just to produce the value for that case.
>
> (reduce #'bin+ args :if-empty 0)
>
> equivalent to:
>
> (if (zerop (length args)) (reduce #'bin args) 0)

Did you mean

(if (zerop (length args)) 0 (reduce #'bin+ args))

? This is equivalent to

(if args (reduce #'bin+ args) 0)

and of same code length as

(reduce #'bin+ args :if-empty 0)

.