* Modules and GOOPS @ 2016-07-27 17:53 Kovacsics Róbert 2016-07-27 19:44 ` Jan Wedekind 2016-07-28 21:14 ` David Pirotte 0 siblings, 2 replies; 11+ messages in thread From: Kovacsics Róbert @ 2016-07-27 17:53 UTC (permalink / raw) To: guile-user Hello! I have trouble with getting GOOPS and modules to co-operate. What I am trying to do is to have 'A subclass B' where A is something akin to an abstract class, that is it has generic "x" for which it provides no implementation. This is my minimum broken example: ; <mbe/a.scm>= (define-module (mbe a) #:use-module (oop goops) #:export (<a> x y)) (define-class <a> ()) (define-generic x) (define-generic y) (define-method (y (a <a>)) (display (x a))) ; <mbe/b.scm>= (define-module (mbe b) #:use-module (oop goops) #:use-module (mbe a) #:export (<b> x)) (define-class <b> (<a>)) (define-method (x (b <b>)) 'b) ; <mbe/test.scm>= (define-module (mbe test) #:use-module (oop goops) #:use-module (mbe a) #:use-module (mbe b) #:duplicates (merge-generics)) (y (make <b>)) and when I type "(use-modules (mbe test))" in guile, I get While compiling expression: ERROR: No applicable method for #<<generic> x (0)> in call (x #<<b> 23ccdd0>) (which shows that the generic function "x" has no implementation as far as I can work it out, due to accessibility. When I don't use separate modules, it works.) Am I using the right sort of approach? I was thinking modules, for extensibility. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-27 17:53 Modules and GOOPS Kovacsics Róbert @ 2016-07-27 19:44 ` Jan Wedekind 2016-07-28 22:36 ` David Pirotte 2016-07-28 21:14 ` David Pirotte 1 sibling, 1 reply; 11+ messages in thread From: Jan Wedekind @ 2016-07-27 19:44 UTC (permalink / raw) To: Kovacsics Róbert; +Cc: guile-user On Wed, 27 Jul 2016, Kovacsics Róbert wrote: > Hello! > > I have trouble with getting GOOPS and modules to co-operate. What I am > trying to do is to have 'A subclass B' where A is something akin to an > abstract class, that is it has generic "x" for which it provides no > implementation. This is my minimum broken example: > > > ; <mbe/a.scm>= > (define-module (mbe a) > #:use-module (oop goops) > #:export (<a> x y)) > > (define-class <a> ()) > > (define-generic x) > (define-generic y) > > (define-method (y (a <a>)) > (display (x a))) > > ; <mbe/b.scm>= > (define-module (mbe b) > #:use-module (oop goops) > #:use-module (mbe a) > #:export (<b> x)) > > (define-class <b> (<a>)) > > (define-method (x (b <b>)) > 'b) > > ; <mbe/test.scm>= > (define-module (mbe test) > #:use-module (oop goops) > #:use-module (mbe a) > #:use-module (mbe b) > #:duplicates (merge-generics)) > > (y (make <b>)) > > > and when I type "(use-modules (mbe test))" in guile, I get > > > While compiling expression: > ERROR: No applicable method for #<<generic> x (0)> in call (x #<<b> 23ccdd0>) > > (which shows that the generic function "x" has no implementation as > far as I can work it out, due to accessibility. When I don't use > separate modules, it works.) > > Am I using the right sort of approach? I was thinking modules, for > extensibility. > > Having mbe/b.scm *not* export "x" works but I am not sure whether that is the solution you are looking for: ; <mbe/a.scm>= (define-module (mbe a) #:use-module (oop goops) #:export (<a> x y)) (define-class <a> ()) (define-generic x) (define-generic y) (define-method (y (a <a>)) (display (x a))) ; <mbe/b.scm>= (define-module (mbe b) #:use-module (oop goops) #:use-module (mbe a) #:export (<b>)) (define-class <b> (<a>)) (define-method (x (b <b>)) 'b) ; <mbe/test.scm>= (define-module (mbe test) #:use-module (oop goops) #:use-module (mbe a) #:use-module (mbe b) #:duplicates (merge-generics)) (y (make <b>)) Has anybody managed to get the "merge-generics" handler to work? I used to have this in my $HOME/.guile configuration but it didn't seem to have any effect: (default-duplicate-binding-handler '(merge-generics replace warn-override-core warn last)) ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-27 19:44 ` Jan Wedekind @ 2016-07-28 22:36 ` David Pirotte 0 siblings, 0 replies; 11+ messages in thread From: David Pirotte @ 2016-07-28 22:36 UTC (permalink / raw) To: Jan Wedekind; +Cc: guile-user [-- Attachment #1: Type: text/plain, Size: 854 bytes --] Hello, > Has anybody managed to get the "merge-generics" handler to work? I used to > have this in my $HOME/.guile configuration but it didn't seem to have any > effect: > > (default-duplicate-binding-handler '(merge-generics replace warn-override-core > warn last)) You need to import (oop goops), may be you do so in your .guile config file, I can't tell from your email. Note that this 'only' would not solve the question raised by the original email of this thread. Anyway, it's not a good idea, imo, to put this in .guile, because not only you need to have this properly set at load and compile, but your users too. I suggest you read my 'just posted' answer to the original email of this thread, grab and read the grip related example links I pasted and do take a special attention to the last sentence as well. David. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 473 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-27 17:53 Modules and GOOPS Kovacsics Róbert 2016-07-27 19:44 ` Jan Wedekind @ 2016-07-28 21:14 ` David Pirotte 2016-07-29 5:17 ` David Pirotte 2016-07-29 17:00 ` Kovacsics Róbert 1 sibling, 2 replies; 11+ messages in thread From: David Pirotte @ 2016-07-28 21:14 UTC (permalink / raw) To: Kovacsics Róbert; +Cc: guile-user [-- Attachment #1: Type: text/plain, Size: 4451 bytes --] Hello, Before anything else, note that I speak on my own behalf here, not in the name of Guile. I'm saying this because I have an opinionated opinion about Goops, its actual 'design/problems/limitations/bugs' [depending of your point of view], why and how we should change this, as well as how users should use it, precisely regarding, but not limited to, generic functions and the module system, among other things. > I have trouble with getting GOOPS and modules to co-operate. What I am > trying to do is to have 'A subclass B' where A is something akin to an > abstract class, that is it has generic "x" for which it provides no > implementation. This is my minimum broken example: First, generic functions are 'containers', that are not associated, and do not pertain to any class. <a> does not have a generic function x: obviously, this _is_ the beauty (and one of the reason why it's been design this way) since this way, the entire knowledge, except for slot-ref and slot-set! [1] of a generic function multi method polymorphic dispatch system is in user methods and procedures called by these methods; this means, unlike it's been said on this ML several time, unless you use slot-set! (same for Guile set!, no diff wrt Goops here) and class redefinition, Goops is perfectly 'compatible' with functional programming; [1] same problem for define-record, which are not more neither less 'functional' then Goops, imo. Then unlike you've been told by others, I do not recommend to define generic function, they are just 'containers', the system creates them for you and it is an error [not implemented by Guile] to redefine a generic function. With the last in mind, manually defining GF will work if you play with a couple of your own modules, but it will almost certainly fail for large system. But if you do so, define generic functions manually, then I recommend do it in another module. > ; <mbe/a.scm>= > (define-module (mbe a) > #:use-module (oop goops) > #:export (<a> x y)) > > (define-class <a> ()) > > (define-generic x) > (define-generic y) > > (define-method (y (a <a>)) > (display (x a))) > > ; <mbe/b.scm>= > (define-module (mbe b) > #:use-module (oop goops) > #:use-module (mbe a) > #:export (<b> x)) It will work if you #:re-export (x): #:export (<b>) #:re-export (x)) But that not good enough, imo. We precisely _do not_ want to know if we have to use #:export or #:re-export, what we want here is the system to do that for us. I wrote a macro which does the check 'if-exists' for us and either #:export or #:re-export adequately, it's here, fell free to use it: http://git.savannah.gnu.org/cgit/grip.git/tree/grip/g-export.scm You should use it _only_ for getters, setters, accessors and methods, obviously! here is an example of use http://git.savannah.gnu.org/cgit/grip.git/tree/grip/clutter/grid.scm Make sure your class names are unique i the entire 'system' and always use #:export <class name>: this will always create a fresh new binding, and so, unlike in CLOS, won't trigger a class redefinition if it would need to. This said, unless you really know what you're doing, or for pure experimental reasons, don't write 'production' code that rely on class redefinition. > (define-class <b> (<a>)) > > (define-method (x (b <b>)) > 'b) > > ; <mbe/test.scm>= > (define-module (mbe test) > #:use-module (oop goops) > #:use-module (mbe a) > #:use-module (mbe b) > #:duplicates (merge-generics)) You should add merge-generics to the default handlers: scheme@(guile-user)> (default-duplicate-binding-handler) $5 = (replace warn-override-core warn last) So you'd have #:duplicates (merge-generics replace warn-override-core warn last) Note that you still have to set these in your repl (and any script of yours), if you import more then 1 module defining a GF. Here is an example of script: http://git.savannah.gnu.org/cgit/grip.git/tree/grip/clutter/examples/bouncer.in [ line 38 - 41 Also note that in Guile-2.0, module definitions (ice-9/boot.scm define-modules* macro) were calling (default-duplicate-binding-handler), so it was not necessary to declare #:duplicates in each module. This great global parameter setting, and API IMO, has been withdrawn in Guile-2.2, which hard codes duplicate handlers 'as in the manual'. David. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 473 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-28 21:14 ` David Pirotte @ 2016-07-29 5:17 ` David Pirotte 2016-07-29 17:00 ` Kovacsics Róbert 1 sibling, 0 replies; 11+ messages in thread From: David Pirotte @ 2016-07-29 5:17 UTC (permalink / raw) To: Kovacsics Róbert; +Cc: guile-user [-- Attachment #1: Type: text/plain, Size: 658 bytes --] Re, > ... > This great global parameter setting, and API IMO, has been withdrawn in Guile-2.2, > which hard codes duplicate handlers 'as in the manual'. This above sentence is ambiguous/incomplete, here is more accurate 'version', hopefully: This great global parameter setting, and API IMO, has been withdrawn in Guile-2.2. In 2.2, when a module does not declare its duplicate handlers set, using the #:duplicates module directive, then Guile 2.2 won't read the global parameter setting anymore, as it did in 2.0, it will assume instead that the user wants the default duplicate handlers set, as specified in the manual. David. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 473 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-28 21:14 ` David Pirotte 2016-07-29 5:17 ` David Pirotte @ 2016-07-29 17:00 ` Kovacsics Róbert 2016-07-29 18:00 ` Marko Rauhamaa 2016-07-31 2:35 ` David Pirotte 1 sibling, 2 replies; 11+ messages in thread From: Kovacsics Róbert @ 2016-07-29 17:00 UTC (permalink / raw) To: David Pirotte; +Cc: guile-user First, thank you for your detailed answer! On 28 July 2016 at 22:14, David Pirotte <david@altosw.be> wrote: > First, generic functions are 'containers', that are not associated, and do not > pertain to any class. <a> does not have a generic function x: Thank you, I am still thinking in Java terms at the moment. > Then unlike you've been told by others, I do not recommend to define generic > function, they are just 'containers', the system creates them for you and it is an > error [not implemented by Guile] to redefine a generic function. With the last in > mind, manually defining GF will work if you play with a couple of your own modules, > but it will almost certainly fail for large system. So what is the right approach when I'm implementing textbook data structures (rather than want to use the given ones, for learning reasons) and want to implement a set. On this set, I want to write a method "closure" that computes all the elements of the set given a function on the set elements, such that for any call to the function with an element of the set, the result will also be in the set. This is the same code for all implementation, but depends on implementation specific code such as "contains?" and "add". Then I want to implement different sets, e.g. red-black trees, AVL trees, etc. The plan was something like this, but I think I may be trying to achieve it wrong, or at least the unidiomatic way: ; <sets/set.scm>= (define-module (sets set) #:use-module (oop goops) #:export (<set> add ... closure)) (define-class <set> ()) (define-generic add) ... (define-method (closure (set <set>) (function <proceedure>)) ... contains? ... add ... ) ; <sets/red-black-tee-set.scm>= (define-module (sets red-black-tree) #:use-module (oop goops) #:use-module (sets set) #:export (<red-black-tree>)) (define-class <red-black-tree> (<set>)) (define-method (add (tree <red-black-tree>)) ...) ; <mbe/test.scm>= ... Code to exercise methods ... > But if you do so, define generic functions manually, then I recommend do it in > another module. So I could move the add, etc, methods out into another module, if that is the way to do it, but I need them, because without having them, Guile will complain with "unbound variable: add". But this is a very classes-contain-methods approach and given what you said, makes me think that I'm doing this wrong thing. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-29 17:00 ` Kovacsics Róbert @ 2016-07-29 18:00 ` Marko Rauhamaa 2016-07-31 3:59 ` David Pirotte 2016-07-31 10:44 ` Chris Vine 2016-07-31 2:35 ` David Pirotte 1 sibling, 2 replies; 11+ messages in thread From: Marko Rauhamaa @ 2016-07-29 18:00 UTC (permalink / raw) To: Kovacsics Róbert; +Cc: guile-user, David Pirotte Kovacsics Róbert <kovirobi@gmail.com>: > Thank you, I am still thinking in Java terms at the moment. > > [...] > > But this is a very classes-contain-methods approach and given what you > said, makes me think that I'm doing this wrong thing. I'm thinking GOOPS is the wrong thing here. A better, more Schemey way is hiding in plain sight. Look at how ports are created and manipulated. You have a rich set of methods that take the best from Scheme and the classic object/method paradigm, eg: (with-output-to-string thunk) (with-input-from-file filename thunk) (port-filename port) (close-port port) More generally, take a look at <URL: http://www.delorie.com/gnu/docs/guile/guile-tut_10.html> and how MAKE-CELL has been defined. That's true OOP without classes or slots. Marko ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-29 18:00 ` Marko Rauhamaa @ 2016-07-31 3:59 ` David Pirotte 2016-07-31 10:44 ` Chris Vine 1 sibling, 0 replies; 11+ messages in thread From: David Pirotte @ 2016-07-31 3:59 UTC (permalink / raw) To: Marko Rauhamaa; +Cc: guile-user [-- Attachment #1: Type: text/plain, Size: 928 bytes --] Hi Róbert, > More generally, take a look at <URL: > http://www.delorie.com/gnu/docs/guile/guile-tut_10.html> and how > MAKE-CELL has been defined. That's true OOP without classes or slots. IMO, this is exactly what you don't want. You'll find some answers to why in the following article, if you are interested: CLOS: Integrating Object-Oriented and Functional Programming Richard P. Gabriel Lucid, Inc. Jon L White Lucid, Inc. Daniel G. Bobrow Xerox PARC May 3, 2004 I also suggest you read the Stklos Object System (on which Goops is based), online manual pages [1]: they are easier to read (then our Goops ref man) and have some beginner examples (and some links (to a CLOS tutorial also): note that Sklos syntax is slightly different, but no big deal. David. [1] http://www.stklos.net/Doc/html/stklos-ref-8.html#STklos-Object-System http://www.aiai.ed.ac.uk/~jeff/clos-guide.html [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 473 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-29 18:00 ` Marko Rauhamaa 2016-07-31 3:59 ` David Pirotte @ 2016-07-31 10:44 ` Chris Vine 2016-07-31 16:38 ` Marko Rauhamaa 1 sibling, 1 reply; 11+ messages in thread From: Chris Vine @ 2016-07-31 10:44 UTC (permalink / raw) To: guile-user On Fri, 29 Jul 2016 21:00:42 +0300 Marko Rauhamaa <marko@pacujo.net> wrote: [snip] > More generally, take a look at <URL: > http://www.delorie.com/gnu/docs/guile/guile-tut_10.html> and how > MAKE-CELL has been defined. That's true OOP without classes or slots. For that simple kind of use you might as well use records. R6RS records are also inheritable, so you can construct type heirarchies; SRFI-9 records are not. Guile provides both. Chris ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-31 10:44 ` Chris Vine @ 2016-07-31 16:38 ` Marko Rauhamaa 0 siblings, 0 replies; 11+ messages in thread From: Marko Rauhamaa @ 2016-07-31 16:38 UTC (permalink / raw) To: Chris Vine; +Cc: guile-user Chris Vine <chris@cvine.freeserve.co.uk>: > On Fri, 29 Jul 2016 21:00:42 +0300 > Marko Rauhamaa <marko@pacujo.net> wrote: > [snip] >> More generally, take a look at <URL: >> http://www.delorie.com/gnu/docs/guile/guile-tut_10.html> and how >> MAKE-CELL has been defined. That's true OOP without classes or slots. > > For that simple kind of use you might as well use records. R6RS > records are also inheritable, so you can construct type heirarchies; > SRFI-9 records are not. Guile provides both. The key is not to specify types (records or otherwise). Provide a constructor plus opaque objects that have methods. As for the "simple kind of use," there is no need for anything more complicated in object-oriented programming. How would the MAKE-CELL example above benefit from R6RS records? Marko ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Modules and GOOPS 2016-07-29 17:00 ` Kovacsics Róbert 2016-07-29 18:00 ` Marko Rauhamaa @ 2016-07-31 2:35 ` David Pirotte 1 sibling, 0 replies; 11+ messages in thread From: David Pirotte @ 2016-07-31 2:35 UTC (permalink / raw) To: Kovacsics Róbert; +Cc: guile-user [-- Attachment #1: Type: text/plain, Size: 2637 bytes --] Hello, > First, thank you for your detailed answer! Welcome > So what is the right approach when I'm implementing textbook data > structures (rather than want to use the given ones, for learning > reasons) and want to implement a set. On this set, I want to write a > method "closure" that computes all the elements of the set given a > ... I won't have time to help you to design the all thing, but i can review small and complete (no ...) code snipset. The code below is incomplete. > ; <sets/set.scm>= > (define-module (sets set) > #:use-module (oop goops) > #:export (<set> add ... closure)) > > (define-class <set> ()) > > (define-generic add) > ... > > (define-method (closure (set <set>) (function <proceedure>)) > ... contains? ... add ... ) this is indeed not a very good design, imo: the fact that your <set> is an 'empty' class, and with no applicable methods for the all the methods it calls in closure, are the symptoms, imo, that this is not a good design > ; <sets/red-black-tee-set.scm>= > (define-module (sets red-black-tree) > #:use-module (oop goops) > #:use-module (sets set) > #:export (<red-black-tree>)) > > (define-class <red-black-tree> (<set>)) > > (define-method (add (tree <red-black-tree>)) > ...) I can only give an opinion, and it is only an opinion, if you provide full code snipset: and your add method lacks an argument to add :) > So I could move the add, etc, methods out into another module, if that > is the way to do it Nope, I did not say that, I did say that if you want to manually define generic functions, then do it in a separate module, and imports that module when necessary. Although not strictly necessary technically speaking, we generally define methods in the same module as the one where the class of its first argument (used to dispatch) is defined. Just look at some of the clutter examples (links i previous email)... > Guile will complain with "unbound variable: add". But this is a very > classes-contain-methods approach and given what you said, makes me > think that I'm doing this wrong thing. The fact that you manually define the generic function "add" gives the 'illusion' the design is good, but in fact, (add (make <set>) <element>) will fail with no applicable method, which imo, is a sign that the¬this design is not good. The fact that the GF definition is in the (sets set) module does not make the design any better. If you persist in manually defining GF, do it in another module, that all other module which needs them imports of course ... David. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 473 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2016-07-31 16:38 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-07-27 17:53 Modules and GOOPS Kovacsics Róbert 2016-07-27 19:44 ` Jan Wedekind 2016-07-28 22:36 ` David Pirotte 2016-07-28 21:14 ` David Pirotte 2016-07-29 5:17 ` David Pirotte 2016-07-29 17:00 ` Kovacsics Róbert 2016-07-29 18:00 ` Marko Rauhamaa 2016-07-31 3:59 ` David Pirotte 2016-07-31 10:44 ` Chris Vine 2016-07-31 16:38 ` Marko Rauhamaa 2016-07-31 2:35 ` David Pirotte
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).