From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Eric Abrahamsen Newsgroups: gmane.emacs.help Subject: Re: EIEIO built in methods -- question Date: Thu, 13 Jun 2013 13:11:55 +0800 Message-ID: <8761xid278.fsf@ericabrahamsen.net> References: <87txl77fd3.fsf@ericabrahamsen.net> <87li6jjy81.fsf@kuiper.lan.informatimago.com> <874nd7j9kh.fsf@kuiper.lan.informatimago.com> <87fvwqq85n.fsf@arcor.de> <87hah5jssd.fsf@ericabrahamsen.net> <87wqpznxk7.fsf@arcor.de> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1371100346 13469 80.91.229.3 (13 Jun 2013 05:12:26 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 13 Jun 2013 05:12:26 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Thu Jun 13 07:12:26 2013 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Umzph-0006Gj-Sb for geh-help-gnu-emacs@m.gmane.org; Thu, 13 Jun 2013 07:12:26 +0200 Original-Received: from localhost ([::1]:58376 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Umzph-0005sE-9r for geh-help-gnu-emacs@m.gmane.org; Thu, 13 Jun 2013 01:12:25 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:59040) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UmzpQ-0005kd-Rh for help-gnu-emacs@gnu.org; Thu, 13 Jun 2013 01:12:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UmzpM-0000fq-7t for help-gnu-emacs@gnu.org; Thu, 13 Jun 2013 01:12:08 -0400 Original-Received: from plane.gmane.org ([80.91.229.3]:44082) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UmzpL-0000fY-UH for help-gnu-emacs@gnu.org; Thu, 13 Jun 2013 01:12:04 -0400 Original-Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1UmzpJ-00060H-Aq for help-gnu-emacs@gnu.org; Thu, 13 Jun 2013 07:12:01 +0200 Original-Received: from 50.56.99.223 ([50.56.99.223]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 13 Jun 2013 07:12:01 +0200 Original-Received: from eric by 50.56.99.223 with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 13 Jun 2013 07:12:01 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 129 Original-X-Complaints-To: usenet@ger.gmane.org X-Gmane-NNTP-Posting-Host: 50.56.99.223 User-Agent: Gnus/5.130008 (Ma Gnus v0.8) Emacs/24.3 (gnu/linux) Cancel-Lock: sha1:kUnnzTzlX4vJsouSfIeuiHMrgSs= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 80.91.229.3 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:91487 Archived-At: David Engster writes: > Since you want to meddle with the actual creation of objects, I'm afraid > the issues Pascal mentions are at the core of the problems you're > currently experiencing. > > I'll try to answer your question as best as I can, but my EIEIO&CLOS-fu > is pretty rusty (and was never particularly good to start with), so > please take the following with a grain of salt and prepend an 'AFAIK' in > your mind. > >> Testing indicates >> that this works perfectly well: >> >> (defclass persisty (eieio-persistent) >> ()) >> >> (defmethod initialize-instance ((obj persisty) slots) >> (message "slots: %s" slots) >> (call-next-method obj slots)) >> >> I have access to `slots', can short-circuit initialization, and the >> object is created as expected. Surely that's enough? > > But, as the name says, `initialize-instance' only initializes the newly > created instance; it does not return it. So there's no way for you to > return the existing singleton. The only thing you could do is throw an > error. Oh dear, something is very confused here! My understanding of the CLOS/EIEIO model of generic methods and inheritance is that you're basically just creating a glorified hook that gets called as one of a chain of hooks, and that you continue the chain with call-next-method. It's call-next-method that calls a method that produces a return value, not my actual implementation of initialize-instance. The whole thing in a nutshell: (defvar bad-file-name "/home/eric/bad.txt") (defclass persisty (eieio-persistent) ()) (defmethod initialize-instance ((obj persisty) slots) (let ((file-name (plist-get slots :file))) (if (equal file-name bad-file-name) (error "You can't use that file") (message "You made %s" file-name)) (call-next-method obj slots))) ELISP> (setq g (make-instance 'persisty "good" :file "/home/eric/good.txt")) [object persisty "good" "/home/eric/good.txt"] <--- produces success message ELISP> (setq b (make-instance 'persisty "bad" :file "/home/eric/bad.txt")) *** Eval error *** You can't use that file ELISP> b *** Eval error *** Symbol's value as variable is void: b Unless there's some potential fatal flaw with this that I'm not seeing, this is precisely the behavior I wanted. >> I like the idea of keeping the full list of files in a class-allocated >> slot. If it's a problem that the slot only exists after the first >> instance has been created, that seems like something that can be >> accounted for in `initialize-instance' as well... > > In initialize-instance, the instance is already created. > >> One thing I'm still confused about (and if I'm going to provide a doc >> patch, this is exactly what I'd like to address) is the relationship >> between `constructor', `initialize-instance' and `shared-initialize'. >> Obviously I can see that they call each other in that order, but I don't >> understand when you'd want to override one vs the other. > > In a nutshell: The 'constructor' actually creates a new instance and > returns it, and it uses `initialize-instance' to initialize it, which > again calls `shared-initialize'. Ha, though what you say here is basically a restatement of what I could see for myself in the code, it only just made sense, thank you. I think you're right -- I'm not used to seeing the initialization process broken into several steps, that was the only problem. I'm a little curious as to why overloading the constructor only seems to work with the :static specification (it doesn't appear to get called at all, otherwise). I'll do some more experimentation with class-allocated slots, that's still a bit opaque to me. [...] >> As far as I can tell the only difference is that `constructor' has >> access to the string object name (the point of which I've never >> understood), and `initialize-instance' doesn't. > > The object name is also an EIEIO thing. It's mainly there to ease > debugging. For instance, we create lot of databases in Semantic (which > are objects) to store symbols from source files in certain > directories. The name of these databases is equal to the directory > name. This makes inspection in the object browser much easier, since you > directly see the directory instead of some cryptic code. However, you > don't have to care about it, and `make-instance' will just use the class > name by default. That was interesting, thanks. For persistent objects, in particular, it does seem to make sense to use the save file as the name. >> Thanks for the offer! It would be something simple, just about using >> `initialize-instance', `constructor' if I ever understand exactly what >> that does, `object-print', and a few other methods in that neighborhood. >> As I mentioned I'm coming at this from Python experience, and wanted to >> write a basic how-to that would make sense to people with OO experience >> in other languages. > > IMHO you best learn CLOS by forgetting OOP idioms from other > languages. You'll just get confused. I recommend reading the two > chapters on OOP from the Seibel-Book, which you can read online here: I think I've got a handle on that now. I first read those chapters two or three years ago and was *totally* baffled -- I couldn't grok that methods could be separated from objects. I revisited it recently, though, and it made quite a bit of sense (and made me wish, once again, that my emacs ran on SBCL...). I don't think I'm necessarily stuck in Python/C++ etc, but I do think it's helpful to tell people "what it looks like over here". Thanks for your help, Eric