[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#19459: #:export does not honor the merge-generics contract
From: |
David Pirotte |
Subject: |
bug#19459: #:export does not honor the merge-generics contract |
Date: |
Thu, 23 Jun 2016 16:23:21 -0300 |
Hi Andy,
> > (define-module (a)
> > #:use-module (oop goops)
> > #:export (<a>
> > !width
> > get-width
> > set-width))
> Here you export four bindings: one class and three generics. Those
> three generics have methods on <a>.
> > (define-module (b)
> > #:use-module (oop goops)
> > #:use-module (a)
> Here you import the previous four bindings.
> > #:export (<b>
> > !width
> > get-width
> > set-width))
> However here you declare that you are going to export four new
> bindings.
> ...
Under the exact circumstances of the original email, I disagree, see below.
From the original email, you only kept the module defs and explains
here in your
answer the expected behavior in normal circumstances: the behavior one
can
expect from the default Guile configuration. Fine, but that's not the
what
the original email was complaining about :)
> AFAIU there is no bug here. David WDYT?
IMO it is a bug, and to be honest, IMO it is a serious one: a user should never
have
to use #:re-export for generic functions once he/she did ask to merge duplicate
generics, because under this setting, there can be 1 and only 1 generic
function, at
any time in any module. Under these circumstances, it is the generic function
as the
module 'sees it' that the user export, not the generic function as the module
sees
it before import(s)
if imported, then that generic is 'filled in' with new methods, it is
_not_
created [should not be created], hence #:export is the 'culprit',
because as
it is it does not look if a generic exists and create a new one
arbitrarily,
against the user 'wish'. It can only do so if there is no imported one.
So, IMO, under the '(merge-generics ...) setting of the original email (b)
exports 1
new binding and 3 generic functions that were already defined by (a), but/and
'filled' with 3 additional methods. The module (b) exports the generic function
'as
it has it'.
There is another way, maybe, to look at this anomaly: if you comment the export
for
get-width and set-width from the (b) module, it works:
scheme@(guile-user)> ,use (b)
scheme@(guile-user)> (make <b>)
$4 = #<<b> 2051a40>
because within the module (b), the generics set-width and get-width were
imported
from (a), not created [or 'immediately' merged, implementation detail...], and
filed
with the (b) methods. #:export however dismantle this to export a new generic
[but
the user ask to merge them, so it breaks the user 'contract'] only containing
the (b)
methods, which is a bug.
Last but not least, when a user imports (b) and run (make <b>), he is not
himself
calling set-width or get-width: exported or not, the code being run by make
should
run within the (b) module, and in the (b) module the generic functions have been
merged,, so can not [should] raise an error. If you follow your idea/position,
it
should only raise an error if I do (get-width (make <a>)) [but then the system
might
raise the undefined <a> class first..., but you get the idea I guess.
FIWIW, It's been years that I don't use #:export because of this bug, I defined
my
own g-export syntax, based on guile's module source code, here:
http://git.savannah.gnu.org/cgit/grip.git/tree/grip/g-export.scm
It would be really good if it be fixed in 2.0.12 and master though.
Cheers,
David
pgpFT2eYaGf80.pgp
Description: OpenPGP digital signature