guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: guile-1.5.1 and deprecated ...


From: Marius Vollmer
Subject: Re: guile-1.5.1 and deprecated ...
Date: 24 Aug 2001 00:33:46 +0200
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.0.102

Thomas Wawrzinek <address@hidden> writes:

> address@hidden wrote:
> 
>  > By using the `:select' option of `:use-module', you can import the two
>  > variables without a name conflict.
> 
> You can do so, but I believe there are cases where you don't want
> to. Imagine a higher order function that is defined in terms of generic
> methods, a (similar) case Java's interfaces were designed for. This should
> work with generic methods from different modules too, IMHO.

But it does!  the module system is about names, and generic functions
are not about names.  Functions don't have names, and the name is not
part of the dispatching algorithm of generic functions.

I don't see how we can cleanly define a behavior for generic functions
that takes into account the module of the code that calls a generic
function.  I'm very sure that whatever we might do, it will in the end
turn out to be inelegant and full of its own surprises.

Keeping the semantics of generic functions and the module system
separate might sometimes feel inconvenient, but it allows us to have
semantics that are simple and easy to understand.


There might well be cases where the module system and generic
functions do not work as smoothly together as one could want for a
certain specific way of using them.  In such a case, I'm all for
providing convenient ways to support the paradigm, but they should be
explicit.

For example, you might want to merge two generic functions when
importing their variables from two modules.  I don't want to make
merging the default behavior, but it can be an option.  Using Rob's
example:

    (define-module (posix))
    (define-method (open (fd <integer>)))
    (export open)

    (define-module (kitchen))
    (define-method (open (x <jar>)))
    (export open)

say you have a module that wants to use both `open' functions.  Since
these functions are independent and only have the same name by chance,
it makes sense to rename them upon import:

    (define-module (bla)
      :use-module ((posix) :select ((open . posix-open)))
      :use-module ((kitchen) :select ((open . kitchen-open))))
    (define stdin (posix-open 0))
    (define lecker (kitchen-open (pick-from-rear-of-fridge)))

If you do want them to be merged, it would make sense to provide a
`merge-generics' function that you can use explicitely:

    (define-module (bla)
      :use-module ((posix) :select ((open . posix-open)))
      :use-module ((kitchen) :select ((open . kitchen-open))))
    (define open (merge-generics posic-open kitchen-open))

If this is too long winded, one could define a short hand notation
ala:
    
    (define-module (bla))
    (define-merged-generic open (posix) (kitchen))

> Requiring the libraries to sort of inherit a common protocol layer adds
> complexity and/or dependencies.

But it's the same with Java interfaces, is it not?  In any case, I
don't think making the protocol layer manifest in a well defined place
adds complexity.  I don't really like the behavior of `define-method'
either where it defines a new empty generic if one doesn't already
exist.  I always define the generic explicitely with `define-generic'
before adding methods to it.  This gives a natural place to document
the general meaning of the generic function, and the protocol it might
belong to.

> Especially weird if the libraries and higher order function are all
> from different sources (programmers, vendors, whatnot ...)

Either these different sources cooperate, in which case they don't
have a problem agreeing on a place to define the protocol; or they
don't coordinate and intent to be using separate protocols, but there
happen to be naming conflicts between the groups: in this case, the
module system is there to protect the guy who uses code from both
sources by keeping the protocols separate.

> Something else:
> 
> I've played around a bit with Marius' last example.
> [...]
> I need to tell my main module to use the protocol interface:
> 
> (define-module (main)
>   :use-module (oop goops)
>   :use-module (protocol-foo))
> 
> (foo #(1 2 3))
> (foo '(1 2 3))
> 
> Normally, I don't want to know about lower level features to get module A
> running.

You aren't using module A here, you are using the `foo' protocol.
Seems quite natural for me to include its module.

> Worse, I have access to some of the functionality of A and B
> without explicitely requiring them.

This is because A and B decided to provide you with that access.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]