unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: Damien Mattei <damien.mattei@gmail.com>
To: Vivien Kraus <vivien@planete-kraus.eu>
Cc: guile-user <guile-user@gnu.org>
Subject: Re: overload a procedure
Date: Sun, 19 Feb 2023 23:07:48 +0100	[thread overview]
Message-ID: <CADEOadceLgvmN-U2eRZE96iHWLFs_cic_4S88ncgDwLq8HmuwA@mail.gmail.com> (raw)
In-Reply-To: <cc07622b57a50ecaf2035245261e5f2657ba7bd6.camel@planete-kraus.eu>

yes your are right, it works with GOOPS out of the box.
scheme@(guile-user)> (use-modules (oop goops) (srfi srfi-43))
scheme@(guile-user)> (define-method (+ (a <vector>) (b <vector>))
(vector-append a b))
scheme@(guile-user)> (+ #(1 2 3) #(4 5))
$3 = #(1 2 3 4 5)
scheme@(guile-user)> (+ #(1 2 3) #(4 5) #(2 5))
$4 = #(1 2 3 4 5 2 5)
scheme@(guile-user)> (define (add-list-list L1 L2) (map + L1 L2))
scheme@(guile-user)> <vector>
$5 = #<<class> <vector> 102b5a780>
scheme@(guile-user)> <list>
$6 = #<<class> <list> 102b5aa00>
scheme@(guile-user)> (define-method (+ (a <list>) (b <list>))
(add-list-list a b))
scheme@(guile-user)> (+ '(1 2 3) '(4 5 6))
$7 = (5 7 9)
scheme@(guile-user)> (+ '(1 2 3) '(4 5 6) '(7 8 9))
$8 = (12 15 18)
scheme@(guile-user)> (define-method (area (a <number>)) (* a a))
scheme@(guile-user)> (area 3)
$9 = 9
scheme@(guile-user)> (define-method (area (a <number>) (b <number>)) (* a
b))
scheme@(guile-user)> (area 3 4)
$10 = 12
scheme@(guile-user)> {'(1 2 3) + '(4 5 6)}
$11 = (5 7 9)

i wanted a more portable solution, i'm coming near a solution that works
with a procedure, not a macro:

(define (overload-proc orig-funct funct pred-list)

  (display "overload-proc") (newline)
  (define old-funct orig-funct)
  (define new-funct (lambda args ;; args is the list of arguments
     (display "new-funct: ") (display new-funct) (newline)
     (display "new-funct : pred-list = ") (display pred-list) (newline)
     (define pred-arg-list (map cons pred-list args))
     (display "new-funct : pred-arg-list = ") (display pred-arg-list)
(newline)

     (define chk-args (andmap (λ (p) ((car p) (cdr p)))
      pred-arg-list))
     (display "new-funct : chk-args = ") (display chk-args) (newline)
     (display "new-funct : args = ") (display args) (newline)

     (if chk-args
 (begin
   (display "new funct :calling:") (display funct) (newline)
   (apply funct args))
 (begin
   (display "new funct :calling:") (display old-funct) (newline)
   (apply old-funct args)))))

  (display "funct: ") (display funct) (newline)
  (display "orig-funct: ") (display orig-funct) (newline)
  (display "old-funct: ") (display old-funct) (newline)
  (display "new-funct: ") (display new-funct) (newline)

  new-funct)

still a few things to fix like dealing with an arbitrary number of
parameters (what GOOPS do very well) and it will be good:

 scheme@(guile-user)> (load "overload-recursive.scm")
scheme@(guile-user)> (define (add-list-list L1 L2) (map + L1 L2))
scheme@(guile-user)> (define + (overload-proc + add-list-list (list list?
list?)))
overload-proc
funct: #<procedure add-list-list (L1 L2)>
orig-funct: #<procedure + (#:optional _ _ . _)>
old-funct: #<procedure + (#:optional _ _ . _)>
new-funct: #<procedure new-funct args>
scheme@(guile-user)> (+ 2 3)
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)> . 2) (#<procedure
list? (_)> . 3))
new-funct : chk-args = #f
new-funct : args = (2 3)
new funct :calling:#<procedure + (#:optional _ _ . _)>
$1 = 5
scheme@(guile-user)> (+ '(1 2 3) '(4 5 6))
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)> 1 2 3) (#<procedure
list? (_)> 4 5 6))
new-funct : chk-args = #t
new-funct : args = ((1 2 3) (4 5 6))
new funct :calling:#<procedure add-list-list (L1 L2)>
$2 = (5 7 9)
scheme@(guile-user)> (+ '(1 2 3) '(4 5 6) '(7 8 9))
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
In procedure map: List of wrong length: ((1 2 3) (4 5 6) (7 8 9))

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,q
scheme@(guile-user)> (define (add-pair p1 p2) (cons (+ (car p1) (car p2))
(+ (cdr p1) (cdr p2))))
scheme@(guile-user)> (define + (overload-proc + add-pair (list pair?
pair?)))
overload-proc
funct: #<procedure add-pair (p1 p2)>
orig-funct: #<procedure new-funct args>
old-funct: #<procedure new-funct args>
new-funct: #<procedure new-funct args>
scheme@(guile-user)> (+ (cons 1 2) (cons 3 4))
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> 1 . 2) (#<procedure
pair? (_)> 3 . 4))
new-funct : chk-args = #t
new-funct : args = ((1 . 2) (3 . 4))
new funct :calling:#<procedure add-pair (p1 p2)>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> . 1) (#<procedure
pair? (_)> . 3))
new-funct : chk-args = #f
new-funct : args = (1 3)
new funct :calling:#<procedure new-funct args>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)> . 1) (#<procedure
list? (_)> . 3))
new-funct : chk-args = #f
new-funct : args = (1 3)
new funct :calling:#<procedure + (#:optional _ _ . _)>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> . 2) (#<procedure
pair? (_)> . 4))
new-funct : chk-args = #f
new-funct : args = (2 4)
new funct :calling:#<procedure new-funct args>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)> . 2) (#<procedure
list? (_)> . 4))
new-funct : chk-args = #f
new-funct : args = (2 4)
new funct :calling:#<procedure + (#:optional _ _ . _)>
$3 = (4 . 6)
scheme@(guile-user)> (+ 3 4)
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> . 3) (#<procedure
pair? (_)> . 4))
new-funct : chk-args = #f
new-funct : args = (3 4)
new funct :calling:#<procedure new-funct args>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)> . 3) (#<procedure
list? (_)> . 4))
new-funct : chk-args = #f
new-funct : args = (3 4)
new funct :calling:#<procedure + (#:optional _ _ . _)>
$4 = 7
scheme@(guile-user)> (+ '(1 2 3) '(4 5 6))
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> 1 2 3) (#<procedure
pair? (_)> 4 5 6))
new-funct : chk-args = #t
new-funct : args = ((1 2 3) (4 5 6))
new funct :calling:#<procedure add-pair (p1 p2)>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> . 1) (#<procedure
pair? (_)> . 4))
new-funct : chk-args = #f
new-funct : args = (1 4)
new funct :calling:#<procedure new-funct args>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)> . 1) (#<procedure
list? (_)> . 4))
new-funct : chk-args = #f
new-funct : args = (1 4)
new funct :calling:#<procedure + (#:optional _ _ . _)>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> 2 3) (#<procedure
pair? (_)> 5 6))
new-funct : chk-args = #t
new-funct : args = ((2 3) (5 6))
new funct :calling:#<procedure add-pair (p1 p2)>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> . 2) (#<procedure
pair? (_)> . 5))
new-funct : chk-args = #f
new-funct : args = (2 5)
new funct :calling:#<procedure new-funct args>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)> . 2) (#<procedure
list? (_)> . 5))
new-funct : chk-args = #f
new-funct : args = (2 5)
new funct :calling:#<procedure + (#:optional _ _ . _)>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> 3) (#<procedure pair?
(_)> 6))
new-funct : chk-args = #t
new-funct : args = ((3) (6))
new funct :calling:#<procedure add-pair (p1 p2)>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)> . 3) (#<procedure
pair? (_)> . 6))
new-funct : chk-args = #f
new-funct : args = (3 6)
new funct :calling:#<procedure new-funct args>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)> . 3) (#<procedure
list? (_)> . 6))
new-funct : chk-args = #f
new-funct : args = (3 6)
new funct :calling:#<procedure + (#:optional _ _ . _)>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure pair? (_)> #<procedure pair? (_)>)
new-funct : pred-arg-list = ((#<procedure pair? (_)>) (#<procedure pair?
(_)>))
new-funct : chk-args = #f
new-funct : args = (() ())
new funct :calling:#<procedure new-funct args>
new-funct: #<procedure new-funct args>
new-funct : pred-list = (#<procedure list? (_)> #<procedure list? (_)>)
new-funct : pred-arg-list = ((#<procedure list? (_)>) (#<procedure list?
(_)>))
new-funct : chk-args = #t
new-funct : args = (() ())
new funct :calling:#<procedure add-list-list (L1 L2)>
$5 = (5 7 9)
sorry for the verbose output, it is still in developping...
regards,
damien

On Sun, Feb 19, 2023 at 6:52 PM Vivien Kraus <vivien@planete-kraus.eu>
wrote:

> Hi Damien,
>
> Le dimanche 19 février 2023 à 18:45 +0100, Damien Mattei a écrit :
> > ok now i come to the scheme problem implementing the two solutions;
> > in
> > scheme i can not use types so i use type predicates (number? verctor?
> > string? list?....)to identify the good function depending of the
> > parameters
> > types find with the predicates.
> > i tried with macro and recursive function with this solution:
> >
> > example of use::
> > (overload + add-vect-vect vector? vector?)
>
> Did you try GOOPS? It provides that kind of functionality.
>
> (use-modules (oop goops) (srfi srfi-43))
> (define-method (+ (a <vector>) (b <vector>)) (vector-append a b))
> (+ #(1 2 3) #(4 5))
>
> Vivien
>


      reply	other threads:[~2023-02-19 22:07 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-19 17:45 overload a procedure Damien Mattei
2023-02-19 17:52 ` Vivien Kraus
2023-02-19 22:07   ` Damien Mattei [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CADEOadceLgvmN-U2eRZE96iHWLFs_cic_4S88ncgDwLq8HmuwA@mail.gmail.com \
    --to=damien.mattei@gmail.com \
    --cc=guile-user@gnu.org \
    --cc=vivien@planete-kraus.eu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).