[plt-scheme] detecting duplicate internal definitions

From: Eli Barzilay (eli at barzilay.org)
Date: Tue May 11 13:36:14 EDT 2004

On May 11, Doug Orleans wrote:
> Eli Barzilay writes:
>  > Thanks.  However, changing this doesn't work -- the second `defmethod'
>  > gets a syntax-local-context of 'expression...
> I've found this macro useful for making expressions usable in
> internal-definition position (or anywhere else):
>   ;; Helper macro for making an expression usable in any lexical context.
>   (define-syntax (define-dummy stx)
>     (syntax-case stx ()
>       ((_ sym exp)
>        (if (list? (syntax-local-context))
> 	   ;; Internal definition position; generate a dummy binding.
> 	   #`(define #,(car (generate-temporaries #'(sym))) exp)
> 	   ;; Otherwise, don't clutter the namespace.
> 	   #'exp))))
> Then both `defmethod's will turn into `define's, but neither will
> define a generic.

Ugh...  But this is not a general solution either...

>  > *sigh*, as I said, I don't think that this is too reliable, but I
>  > tried something that seems like it might work.  The idea is to
>  > keep a mapping from the definition context to things that were
>  > already defined as generics.
> Heh, I was going to suggest this idea, but I thought it was too
> crazy to bring up.  :)

I thought about it some more, and I don't like it.  The problem is
that I can't even hack defgeneric to solve the problem since you can
always do:

  (define foo (generic ...))

so the only solution would be somewhere along the lines of making
syntax-local-context return some list of identifiers that are already
defined in the current context.  Even with that it is not clear what
should happen with:

  (let ((foo (generic ...)))

So I think that I'll make defmethod never generate a generic binding
when used in a local context, and adding an explanation telling people
that they should always use defgeneric if they want to use local
generics.  (In any case, this is almost always a bad idea -- on every
invocation of the function you'd pay the price for creating a generic
function on top of actually using it.)

> P.S. Slightly different topic, but is it possible to use the new
> `normalize-definition' function from (lib "define.ss" "syntax") to
> allow things like this?
>     (defmethod ((f x y) z) (+ z (- x y)))
>     ((f 5 3) 2) ; => 4
> I think this won't work for arguments with specializers, though,
> because it checks that each argument is an identifier.  But perhaps
> that part could be factored out.

Well, my base.ss defines its own curried forms so this is all
unrelated to syntax/define.ss.  I did consider the above extension at
some point but it doesn't make much sense since it gives you the
illusion that you can dispatch on the second set of arguments, but
when you do:

  (defmethod ((foo (x <integer>)) (y <integer>)) ...)
  (defmethod ((foo (x <integer>)) (y <string>)) ...)

then the second would simply override the first.

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!

Posted on the users mailing list.