Re: Making every goops object applicable
Hi, Krister Svanlund krister.svanl...@gmail.com skribis: Apparently this works by some flag being set by applicable-strukt in libguile for the object and that flag is checked during application, calling the 'procedure slot if it's set with some optimization assuming that 'procedure is the first slot. There’s also a vtable flag that determines whether a struct is applicable: #define SCM_STRUCT_APPLICABLE_P(X)(SCM_STRUCT_VTABLE_FLAG_IS_SET ((X), SCM_VTABLE_FLAG_APPLICABLE)) And indeed, the struct’s procedure is the first slot: #define scm_applicable_struct_index_procedure 0 /* The procedure of an applicable struct. Only valid if the struct's vtable has the applicable flag set. */ For instance, every struct whose vtable is applicable-struct-vtable (defined in struct.c) is applicable. Then you can investigate by looking at the indices defined in struct.h: scheme@(guile-user) (struct-vtable? class) $2 = #t scheme@(guile-user) (struct-ref class 1) ; scm_vtable_index_flags $3 = 12291 scheme@(guile-user) (logand $3 4) ; SCM_VTABLE_FLAG_APPLICABLE_VTABLE $4 = 0 ; → not applicable scheme@(guile-user) (logand (struct-ref applicable-struct-vtable 1) 4) $7 = 4 ; → applicable So you could fiddle with the flags of a class to make its instances applicable: scheme@(guile-user) (define (applicable-struct? s) (logand 4 (struct-ref (struct-vtable (struct-vtable s)) 1))) scheme@(guile-user) (applicable-struct? current-input-port) $27 = 4 scheme@(guile-user) (define (applicable-struct-procedure s) (struct-ref s 0)) scheme@(guile-user) (define-class appclass (class) (foo)) scheme@(guile-user) (struct-set! appclass 1 (logior (struct-ref appclass 1) 4)) $32 = 12295 scheme@(guile-user) (define-class foo () (bar #:init-value (lambda args (pk 'apply args))) #:metaclass appclass) $33 = #appclass foo 16e0d20 scheme@(guile-user) (define f (make foo)) scheme@(guile-user) (applicable-struct? f) $34 = 4 scheme@(guile-user) (applicable-struct-procedure f) $35 = #procedure 1863060 at current input:51:0 args scheme@(guile-user) (f 1 2 3) ;;; (apply (1 2 3)) $36 = (1 2 3) But there should certainly be a higher-level facility. :-) Thanks, Ludo’.
Re: Making every goops object applicable
Krister Svanlund krister.svanl...@gmail.com writes: For example an instance of a class inheriting a class that inherits applicable-struct that defines 'procedure is not applicable. Looking at the code, it is clear that in order for a GOOPS instance to be applicable, it is not enough for applicable-struct to be a superclass. It is also necessary for the _metaclass_ of its class to have the SCM_VTABLE_FLAG_APPLICABLE_VTABLE bit set. One such metaclass is already built-in: applicable-struct-class, which is the metaclass for applicable-struct, but if you'd like to define your own metaclass for applicable objects, you can set the bit manually on the metaclass as described by Ludovic. However, keep in mind that the presence of that bit in the metaclass indicates that the first slot of all instances _must_ be the procedure slot. Mark
Re: terribly complex syntax objects in syntax parse
I wish I had a better answer for you, but unfortunately these enormous syntax-objects are a core part of the 'syntax-case' system. I see no way to eliminate this bloat without moving to a different macro system. Hey one can do what one can do. 1000rows of scheme results currently in 500kB go file mainly due to these syntax objects. On the other hand does the compiler create object data intelligently making sure that eq? objects is created only once? hence a reuse of common subexpressions. That can compress the bloat a bit I suspect! /Stefan Anyway I think you mentioned you wanted a refisgn of the syn On Tue, May 15, 2012 at 12:04 AM, Mark H Weaver m...@netris.org wrote: Hi Stefan, Stefan Israelsson Tampe stefan.ita...@gmail.com writes: syntax-parse is kind of heavy right now. The parser function produced are huge and the main reason is that the stored syntax objects are enormous. Yes, this is very unfortunate. These syntax-objects add a huge amount of bloat to our entire system. The vast majority of each syntax-object is used only if the syntax-object is passed as the first argument to 'datum-syntax'. Of course, most syntax-objects are never passed to 'datum-syntax', but unless the compiler can prove that this will never happen, the bloat must be kept around. I know that Mark Weaver had done something to make these creatures less fatty. I wrote a hack to minimize the size of syntax objects in psyntax-pp.scm. However, the hack cannot safely be used in the general case. It is only safe because I convinced myself and others that the syntax-objects embedded within psyntax-pp.scm will never be passed to 'datum-syntax'. The question is if there is anything a guile user can do? My hack cannot be used by users because it makes assumptions about the internals of psyntax and of our compiler: assumptions that will certainly to be violated in future versions of Guile. I wish I had a better answer for you, but unfortunately these enormous syntax-objects are a core part of the 'syntax-case' system. I see no way to eliminate this bloat without moving to a different macro system. Best, Mark
Re: Empty entries in $GUILE_LOAD_PATH
Hi Mark, Mark H Weaver m...@netris.org skribis: l...@gnu.org (Ludovic Courtès) writes: Try something like: $ GUILE_LOAD_PATH=/foo/bar: make check … and see the LALR tests fail with: ERROR: In procedure primitive-load-path: Unable to find file home/ludo/src/guile/test-suite/lalr/common-test.scm in load path (These tests use ‘load’.) Is that expected? What’s the meaning of empty entries in the load path? It seems to me that a valid load path should never contain empty entries, because the empty string is not a valid path. Apparently ‘search_path’ has always treated as the current directory: $ guile GNU Guile 2.0.5.132-ff4d3 Copyright (C) 1995-2012 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user) (not (not (member %load-path))) $1 = #t scheme@(guile-user) (chdir /etc) scheme@(guile-user) (search-path '() resolv.conf) $2 = resolv.conf (Same with 1.8.) So we probably can’t change that. Should ‘meta/uninstalled-env’ co. clear $GUILE_LOAD_PATH? I don't see why it should. Actually the problem was: scheme@(guile-user) (set! %load-path (cons %load-path)) scheme@(guile-user) (with-fluids ((%file-port-name-canonicalization 'relative)) (port-filename (open-input-file /dev/null))) $1 = dev/null I just fixed it. Comments welcome! Thanks, Ludo’.
Re: how to implement mutual recursive parsers in syntax-parse
On Mon 14 May 2012 21:13, Stefan Israelsson Tampe stefan.ita...@gmail.com writes: (begin (define parser-a code-a ...) (define-syntax a spec-a)) (begin (define parser-b code-b ...) (define-syntax b spec-b)) In racket they manage to evaluate the define-syntax forms before the define-forms cause in the expansion of code-a amd code-b they need the spec's spec-a and spec-b. Do you have any ideas how solve this. I do have a fix for problem but it is not easy to use. Have you tried master? If I understand you correctly I think it should work there. Andy -- http://wingolog.org/
Re: terribly complex syntax objects in syntax parse
On Tue 15 May 2012 17:10, Stefan Israelsson Tampe stefan.ita...@gmail.com writes: Hey one can do what one can do. 1000rows of scheme results currently in 500kB go file mainly due to these syntax objects. That's terrible... On the other hand does the compiler create object data intelligently making sure that eq? objects is created only once? hence a reuse of common subexpressions. That can compress the bloat a bit I suspect! It should do that, yes. If it doesn't, that's a bug! Andy -- http://wingolog.org/
Re: Empty entries in $GUILE_LOAD_PATH
Heya, On Tue 15 May 2012 00:30, Mark H Weaver m...@netris.org writes: It seems to me that a valid load path should never contain empty entries, because the empty string is not a valid path. Traditionally empty path components indicate the current directory, AFAIK. I think they're valid, and if we are not interpreting them that way, that's probably a bug. (Though, as you note, their existence is itself probably a bug; perhaps we should emit a warning if one is found...) Should ‘meta/uninstalled-env’ co. clear $GUILE_LOAD_PATH? I don't see why it should. Me neither. Andy -- http://wingolog.org/
Re: Register VM WIP
On Mon 14 May 2012 23:28, Andrew Gwozdziewycz apg...@gmail.com writes: On Mon, May 14, 2012 at 5:09 PM, Ludovic Courtès l...@gnu.org wrote: Presumably the tricky part will be the register allocator, right? The register based VMs I've seen ignore this issue by allowing for an infinite set of registers. :) Indeed, that's the plan :) The first shot at an allocator will look a lot like the one in (language tree-il analyze). Andy -- http://wingolog.org/
Re: Register VM WIP
Heya Ludovic, On Mon 14 May 2012 23:09, l...@gnu.org (Ludovic Courtès) writes: 6(local-ref 1) 8(make-int8:0) 9(ee?) 10(local-set 2) ;; 12(local-ref 2) ;; → use ‘local-set* 2’, which doesn’t pop 14(br-if-not :L187) ;; - 21 The register VM will do a br-if-= N M ! :LABEL, where ! is a flag indicating that the test is inverted. It addresses the operands directly in registers, no need to push test values. But yes, there are places we could win, like local-sub1 and local-mov, as you say. Regards, Andy -- http://wingolog.org/
Re: GOOPs, MOP and slots
Hi David, A pleasure to get such nice questions about GOOPS :) I have a love/hate relationship with the thing; I've spent a lot of time hacking it but I don't really use it these days. On Fri 11 May 2012 14:19, David Spångberg da...@tunna.org writes: In the CLOS-like language Closette presented in AMOP (The Art of the Metaobject Protocol) there is a generic method named `slot-value-using-class' which is used to access the slots of specific instances. For example this method is used by `slot-value' (`slot-ref' in GOOPs). In AMOP this generic method is used to implement classes where every access and modification of slots is logged. It is also used to implement a class with a kind of dynamic allocation of slots. In GOOPs however the corresponding function `slot-ref-using-class' is not generic. My question is if someone know why this is the case? Or maybe someone can point me to some documentation which may contain information about this? I don't know why it's not generic. Have you taken a look at the corresponding code in Stklos? In general for this kind of question you have to think that GOOPS was implemented from about 1998 to 2002. Since then it has not changed much. I guess the largest change was rewriting parts of it for Guile 2.0, as it used interpreter-specific hacks. However my goal was keeping functionality, not extending the MOP. It could be that making it generic is the right thing, and if Kiczales does it and CLOS does it, then hey, we probably should, too. Basically you need to look at the problem and decide the right thing. It's a bit terrifying in some ways, to modify a really intricate piece of code without a maintainer to tell you what to do, but it's quite possible to do. Do I have it right that you are in Sweden? You should see if you can convince Mikael Djurfeldt to join you for dinner some day ;-) My usecase if anyone wanted to know is to implement python-like attributes as slots for instances. I.e. slots which is not class specific but instead is only related to the current instance. These slots should be accessible by using the standard `slot-ref' and `slot-set! functions in GOOPs. I would consider using eql specializers for the accessors. That way you can specialize to an instance. Of course that's another unimplemented part of the MOP, this time in generic functions. Generic functions are a bit tricky for that, though; for best performance, you need a cache per call site -- an inline cache, as pioneered by self (and smalltalk-80 before it) -- but GOOPS's cache is per-generic. It works, but isn't optimal. I'm not sure how to fix that. My guess is that by making `slot-ref-using-class' generic makes it impossible to memoize slot locations for these kinds of classes. Could be. The MOP is all about permitting efficiency when you use the standard classes. It doesn't prohibit efficiency for others, though, and since GOOPS is mostly written in Scheme now, things should be more flexible. Happy hacking with GOOPS, Andy -- http://wingolog.org/
Re: Do we have a guile-1.8 branch?
On Thu 03 May 2012 00:04, Noah Lavine noah.b.lav...@gmail.com writes: Yes, please remove the ‘release-1.8’ branch. Something like ‘git push origin :release-1.8’ should work (search for “delete” in git-push(1).) Thanks, Ludo’. Oh, I never knew how to do that. It's done now. Cool. It's pretty strange, sometimes if I want to rebase a WIP branch and push a new one, I have to first delete the old one, then push the new one, instead of sending a forced update (i.e. instead of git push origin +wip-foo). Strange things :) Cheers, Andy -- http://wingolog.org/
Re: Making every goops object applicable
Mark H Weaver m...@netris.org writes: Krister Svanlund krister.svanl...@gmail.com writes: For example an instance of a class inheriting a class that inherits applicable-struct that defines 'procedure is not applicable. Looking at the code, it is clear that in order for a GOOPS instance to be applicable, it is not enough for applicable-struct to be a superclass. It is also necessary for the _metaclass_ of its class to have the SCM_VTABLE_FLAG_APPLICABLE_VTABLE bit set. One such metaclass is already built-in: applicable-struct-class, which is the metaclass for applicable-struct, So the solution to Krister's problem is to make sure that every class he's interested in is defined as (define-class whatnot (supers...) ... #:metaclass applicable-struct-class) Right? but if you'd like to define your own metaclass for applicable objects, you can set the bit manually on the metaclass as described by Ludovic. Would this be needed, if the above works? However, keep in mind that the presence of that bit in the metaclass indicates that the first slot of all instances _must_ be the procedure slot. Might the (define-class ... #:metaclass applicable-struct-class) ensure that, by some kind of of compute-slots customisation...? I took a look but unfortunately couldn't see this in the code. Neil
Re: Do you recognize these modules?
Heya TTN, Great to have your hack-power here. On Mon 14 May 2012 19:00, Thien-Thi Nguyen t...@gnuvola.org writes: Also, i can either add a file to branch_release-1-8 (exercising my regained write privs :-D), or post it. What's best? 2.0 is the current stable branch, so any changes should go there first. If it's a build fix or some other fix related to forward-compatibility with 2.0, it can go on 1.8 as well. We should avoid adding interfaces to 1.8, though. When in doubt, it's best (and much appreciated) to mail the list. If no one responds in a few days, go ahead and push it of course. Does that sound sensible to you? Cheers, Andy -- http://wingolog.org/
Re: [PATCH] Turn on more documentation
Howdy, On Sun 06 May 2012 12:14, l...@gnu.org (Ludovic Courtès) writes: The problem is that the auto-generated “Standard Library” section looks very poor in comparison to the rest of the manual. So we should really try hard to write good doc by hands for these, and come up with a handy structure (instead of one node per module, all under “Standard Library”). I agree. I used to think that auto-generation would work as well or better than .texi files, but I think time has definitely proved me wrong, and the GCS right (http://www.gnu.org/prep/standards/html_node/Doc-Strings-and-Manuals.html). The right thing to do is to rework the Standard Library documentation into .texi files. Andy -- http://wingolog.org/
Re: [PATCH] Turn on more documentation
On Mon 14 May 2012 17:14, Noah Lavine noah.b.lav...@gmail.com writes: I think of our current situation as having three top-level lists of functionality, in API Reference, Guile Modules, and Standard Library. How about just merging them into one list? It would be quite a big list. Would that be OK? For me the difference is that nodes of API reference describe functionality that is often not segregated in modules, whereas Guile Modules has nodes that describe modules. What if we merge Guile Modules and Standard Library into one Standard Library node, and keep API Reference as it is? Andy -- http://wingolog.org/
Re: Our temporary guildhall package repository down?
On Fri 04 May 2012 10:25, Nala Ginrut nalagin...@gmail.com writes: http://rotty.yi.org/doro/experimental is unavailable for me. And ijp said it's the same for him. But Rottmann's site is OK. Well, if there's some trouble with his site to put guildhall package repository, I can provide a temporary repository from my web host. I think this may let us test guildhall till it really works for Guile at least. Or we may have one more alternative repository. Could anyone give me all the things of 'experimental' directory? I can upload them at once. And my web host is available at least 2 years. We have guildhall.gnu.org, but we haven't done anything with it. It's a fresh VM. Are you interested in helping administer it? We should figure out a way to collaborate. Andy -- http://wingolog.org/
Re: syntax parse link
On Tue 08 May 2012 17:46, Stefan Israelsson Tampe stefan.ita...@gmail.com writes: I would like to add a link to the syntax-parse repo from guile's home page. I was told to try get the rights to do this myself. If that doesn't work I will need help from any of the maintainers to make the linkage. I've added you to the Guile group. You should be able to make a writable CVS checkout of the web repository. (Yes, CVS. It's incredible. I keep forgetting how to use it.) Anyway the bulk of the web site is in template/ and generated. I think there is a README. It is still horribly complex. Anyway good luck, and ask on IRC when you have problems! Andy -- http://wingolog.org/
Re: stack closures for guile-log
On Tue 08 May 2012 21:16, Stefan Israelsson Tampe stefan.ita...@gmail.com writes: I have three stacks 1. a control stack that stores undo information scheme hooks aka dynamic-wind and stack references to the other stacks. Have you seen dynstack.[ch] on master? 2. stack from which data is allocated from like the bulk of a closure and special pairs 3. a cons stack, e.g. an array of allocated conses I wonder, can you implement these too using something like the dynstack? Andy -- http://wingolog.org/
Re: patch to guile to allow c-code closure interaction for logic programming
On Wed 09 May 2012 18:07, Stefan Israelsson Tampe stefan.ita...@gmail.com writes: I post here a directory of patches and code that can be used to enhance guile to interact nicely with logic programming code written in C. I can reach very good performance using this tool please have a look and comment on it. Would you mind attaching them to the message directly? It's easier to read and comment that way. If you want, you can do the linux kernel thing of one patch per message. But as you like. Cheers, Andy -- http://wingolog.org/
Re: our benchmark-suite
Heya Neil, On Fri 04 May 2012 23:43, Neil Jerram n...@ossau.homelinux.net writes: It turns out I'm already scaling by iteration count - in fact since November 2009. :-) Excellent, so we can scale iteration counts in Guile's git with impunity :) It would be nice for the graphs for individual benchmarks to have an absolute Y axis, in terms of microseconds I guess. Still, I wanted to do something new, so I've added further graphs showing just the last 50 measurements for each benchmark (whereas the existing graphs showed all measurements since my data collection began). The generation of those is still running at the moment, but should be complete in an hour or so. Neat :) (Do you pngcrush these? They seem a little slow to serve.) It would also be nice to have overview graphs from the last 50 days as well, should you have time to hack that up. Thanks for this tool, it's neat :) Andy -- http://wingolog.org/
Re: Functional record setters, a different approach
Hi Mark, Mark H Weaver m...@netris.org skribis: l...@gnu.org (Ludovic Courtès) writes: Mark H Weaver m...@netris.org skribis: l...@gnu.org (Ludovic Courtès) writes: I’ll let you see whether/how you can borrow from this in your code, if that’s fine with you. Okay, will do. Any progress on this? ;-) I apologize for dropping on the ball on this. The primary concern I have with my current approach is that 'define-tagged-inlinable' adds several more huge bloated syntax-objects to the getter macros. Of course, as usual, this bloat will never be used, but everyone must pay for 'datum-syntax' whether they use it or not :-( Are you concerned about the size of ‘srfi-9.go’, or is there some other issue at stake? While I agree that bloating .go files is not satisfying, I would not consider it a showstopper here. I suppose the only way to use fewer syntax objects would be to use a specialize variant of ‘define-tagged-inlinable’, no? That would make the code less elegant. I’m happy to help with updating the docs, for instance, if you want. That would be very helpful, thanks! OK, I’ll do that when the code is checked in. Thanks, Ludo’.
Re: [PATCH] Turn on more documentation
Hi, Andy Wingo wi...@pobox.com skribis: What if we merge Guile Modules and Standard Library into one Standard Library node, and keep API Reference as it is? Sounds good to me. Perhaps “Standard Library” could have sub-sections, like “Data Structures”, “Web”, “XML”, “Texinfo”, etc. Ludo’.
Re: Patches for module/ice-9/occam-channel.scm
Noah Lavine noah.b.lav...@gmail.com writes: Since these are relatively large changes, you'll also need to do a copyright assignment. We assign the copyright on Guile to the Free Software Foundation because under US law, the owner of a copyrighted work is sometimes the only person with the power to sue over violations of copyright. The FSF wants to be able to sue if people violate the GPL, so we assign copyright. I'd just like to add that suing is a last resort and extremely rare, only done when companies use our software and blatantly refuse to give their users the rights that are guaranteed to _all_ users by the GPL. The policy of the FSF regarding GPL violations was explained well by Eben Moglen: http://www.geof.net/research/2006/moglen-notes When I went to work for Richard Stallman in 1993, he said to me at the first instruction over enforcing the GPL, I have a rule. You must never let a request for damages interfere with a settlement for compliance. I thought about that for a moment and I decided that that instruction meant that I could begin every telephone conversation with a violator of the GPL with magic words: We don't want money. When I spoke those words, life got simpler. The next thing I said was, We don't want publicity. The third thing I said was, We want compliance. We won't settle for anything less than compliance, and that's all we want. Now I will show you how to make that ice in the wintertime. And so they gave me compliance. Which had been defined mutually as ice in the wintertime. Unfortunately, there are many corporations that will violate the GPL without remorse unless we have the _ability_ to sue them. Please see http://www.gnu.org/licenses/why-assign.html for more information, or email ass...@gnu.org to fill out a form. I should also mention that I'm _extremely_ allergic to legalese, and can literally count on one hand the number of agreements I have signed in the last decade, but the FSF legalese I was asked to sign was refreshingly fair and reasonable. Mark
Re: Register VM WIP
Hello, The register based VMs I've seen ignore this issue by allowing for an infinite set of registers. :) Indeed, that's the plan :) The first shot at an allocator will look a lot like the one in (language tree-il analyze). That was a bit surprising to me. Do you mean that the register pool will grow and shrink for each function call? Is that why the stack frames can be fixed-size? Thanks, Noah
Re: Our temporary guildhall package repository down?
OK, if there's no anyone interested in it, I'll take it. Guildhall is very important for building more powerful Guile community. I wish it wake up soon. At least we can do some test then contribute to it. On Wed, May 16, 2012 at 4:25 AM, Andy Wingo wi...@pobox.com wrote: On Fri 04 May 2012 10:25, Nala Ginrut nalagin...@gmail.com writes: http://rotty.yi.org/doro/experimental is unavailable for me. And ijp said it's the same for him. But Rottmann's site is OK. Well, if there's some trouble with his site to put guildhall package repository, I can provide a temporary repository from my web host. I think this may let us test guildhall till it really works for Guile at least. Or we may have one more alternative repository. Could anyone give me all the things of 'experimental' directory? I can upload them at once. And my web host is available at least 2 years. We have guildhall.gnu.org, but we haven't done anything with it. It's a fresh VM. Are you interested in helping administer it? We should figure out a way to collaborate. Andy -- http://wingolog.org/
Re: Register VM WIP
Noah Lavine noah.b.lav...@gmail.com writes: The register based VMs I've seen ignore this issue by allowing for an infinite set of registers. :) Indeed, that's the plan :) The first shot at an allocator will look a lot like the one in (language tree-il analyze). That was a bit surprising to me. Do you mean that the register pool will grow and shrink for each function call? Is that why the stack frames can be fixed-size? It's surprising to me for another reason: in order to make the instructions reasonably compact, only a limited number of bits are available in each instruction to specify which registers to use. Mark
Re: Making every goops object applicable
Hi Neil! Neil Jerram n...@ossau.homelinux.net writes: Mark H Weaver m...@netris.org writes: Krister Svanlund krister.svanl...@gmail.com writes: For example an instance of a class inheriting a class that inherits applicable-struct that defines 'procedure is not applicable. Looking at the code, it is clear that in order for a GOOPS instance to be applicable, it is not enough for applicable-struct to be a superclass. It is also necessary for the _metaclass_ of its class to have the SCM_VTABLE_FLAG_APPLICABLE_VTABLE bit set. One such metaclass is already built-in: applicable-struct-class, which is the metaclass for applicable-struct, So the solution to Krister's problem is to make sure that every class he's interested in is defined as (define-class whatnot (supers...) ... #:metaclass applicable-struct-class) Right? That was indeed my suggestion, though your comments below raise an additional complication that I hadn't considered: some additional magic will be needed to ensure that the 'procedure' slot comes first. but if you'd like to define your own metaclass for applicable objects, you can set the bit manually on the metaclass as described by Ludovic. Would this be needed, if the above works? No, but since this is part of an effort to implement Python 3 in Guile, it's possible that they may need to create their own metaclass for other reasons. However, keep in mind that the presence of that bit in the metaclass indicates that the first slot of all instances _must_ be the procedure slot. Might the (define-class ... #:metaclass applicable-struct-class) ensure that, by some kind of of compute-slots customisation...? I guess so, but I'm not convinced that this is the right approach. It now seems reasonably clear that GOOPS has poor support for applicable objects, so we should think about a more proper solution that's easy to use. I don't see why applicable objects should need a custom metaclass. In general, it seems to me that features that require custom metaclasses do not compose well. Subclasses of applicable-struct should just work without users resorting to these hacks. As I've suggested before, the most elegant solution I can think of is to simply make a two-argument generic function called something like 'generic-apply'. I suspect that there's some clever way to make this very fast using the MOP, but I have yet to work out the details. Unfortunately my copy of AMOP is 50 miles away at the moment. Suggestions solicited, and if anyone wants to take the lead on this, I'd be grateful. If not, I'll try to come up with something. Thanks, Mark