From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Daniel Colascione Newsgroups: gmane.emacs.devel Subject: Re: [Emacs-diffs] trunk r116995: cl-lib defstruct introspection Date: Mon, 21 Apr 2014 15:26:21 -0700 Message-ID: <53559B0D.3070505@dancol.org> References: <53555822.3080007@dancol.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="mlaH60sqLUtnQJtksUsreFLBCsJe2fUNO" X-Trace: ger.gmane.org 1398119204 31079 80.91.229.3 (21 Apr 2014 22:26:44 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 21 Apr 2014 22:26:44 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Apr 22 00:26:38 2014 Return-path: Envelope-to: ged-emacs-devel@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 1WcMfe-00007O-AO for ged-emacs-devel@m.gmane.org; Tue, 22 Apr 2014 00:26:38 +0200 Original-Received: from localhost ([::1]:51815 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WcMfd-0002vG-Sf for ged-emacs-devel@m.gmane.org; Mon, 21 Apr 2014 18:26:37 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:38501) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WcMfZ-0002uQ-7u for emacs-devel@gnu.org; Mon, 21 Apr 2014 18:26:34 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WcMfW-0000PE-HV for emacs-devel@gnu.org; Mon, 21 Apr 2014 18:26:33 -0400 Original-Received: from dancol.org ([2600:3c01::f03c:91ff:fedf:adf3]:41120) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WcMfW-0000Nv-4W for emacs-devel@gnu.org; Mon, 21 Apr 2014 18:26:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Type:In-Reply-To:References:Subject:CC:To:MIME-Version:From:Date:Message-ID; bh=eaL6k9ctC08wYDkoX6K1Ie/sh6J9RklYFG13RQ/qTSI=; b=I/i8Fhu5AW1fTFbzYExN4gApUeNDIxhDY4YmcLEtcukru8hLmZ9aZ2D6Aj3VSLjEZfpoEL6r7ebhRODaW3Rjfcc2F4ebnPinnyZB/LYdvH6+IaMae9I85zRFIuBPI0QLsi6aQR95848DDtA1WcfClLj/vjEB6kANfmAZ6lVFanHzBXrJTnjp+Y1OEttqhNQLZTCSoFjkELZvZKkkeK4Kg8zR+J3Z9B4ig3X0TCkBlBgzkJ0MxxC7i17ispqJfCRXdMm+oiQab29/DzAlcOrdqE/BhgqVB1d9nNAxPhxaUX5zP/agAfrIdimgdraRFgbZ+hCCxWVCJwXDDKST2mF2IQ==; Original-Received: from [2620:10d:c083:1003:863a:4bff:fec8:e538] by dancol.org with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.82) (envelope-from ) id 1WcMfU-0004J1-5a; Mon, 21 Apr 2014 15:26:28 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0 In-Reply-To: X-Enigmail-Version: 1.6 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2600:3c01::f03c:91ff:fedf:adf3 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:171551 Archived-At: This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --mlaH60sqLUtnQJtksUsreFLBCsJe2fUNO Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On 04/21/2014 03:03 PM, Stefan Monnier wrote: >> That's new. Using the whole ChaneLog message has been a recommendation= , >> but never a requirement. >=20 > For `elpa', that's true, but for `emacs' it's always been a requirement= , > on the premise that this should/will allow us to drop the ChangeLog > files at some point. Thanks for the clarification. >> Now there's one more step on the commit path, and a useless one at >> that: the changelog entry is available in the change itself and in the= >> message to the mailing list. >=20 > C-x v v can copy the message from ChangeLog for you (and set Author: > and Fixes: at the same time), so it's not so bad. Can it? I tried it in vc-dir and got a completely unrelated ChangeLog hun= k. > The way to fix this, is to make ChangeLog unneeded. First step on this= > path is to provide some way to make `C-x 4 a' usable without ChangeLog.= >=20 >>>> +The @code{cl-defstruct} package also provides a few structure >>>> +introspection functions. >>> I'm curious: when/where did you bump against a need for that? >> I have a few private macros that lexically bind structure slots, >=20 > Which part makes it impossible/impractical to use standard accessors fo= r > that? :conc-name, for starters. Also, :read-only, although you could argue that you shouldn't go around mutating read-only slots anyway. >> and this information is also needed for some interface-generation work= >> I'm thinking of doing. >=20 > Not sure what "interface-generation" means, but it sounds interesting. I'm just playing around at this point --- but the basic idea is that we need some way to connect independent Emacs components, and this mechanism should be more structured than some kind of do-everything-in-a-giant-cond handler function, but much lighter and more comprehensible than EIEIO. One approach is to define COM-like (wait! keep reading!) "interface" structures that bundle useful functions into composeable pieces, then have Emacs components interact in terms of these interfaces. We can make them very lightweight, and let all interfaces inherit from a common interface that lets callers ask for additional functionality: (iface-declare (iface-base nil) "Interface from which all others inherit." ((iface-query instance interface) "Get an implementation of INTERFACE from INSTANCE.")) For example, we could define some project interfaces like this: (iface-declare (project iface-base) ((project-get-root-directory project ) "Find the root directory of PROJECT.") ((project-get project property) "Get a project property PROPERTY.") ((project-put project property value) "Set a project property PROPERTY to VALUE.")) (iface-declare (project-c iface-base) ((project-c-include-directories project file) "Return a list of include directories for FILE in PROJECT. FILE is a fully-qualified name.")) iface-declare defines trivial wrapper functions that make it convenient to call through interface fields. So the generated definition of project-get, for example, would look like this: (defun project-get (inst &rest xargs) "Get a project property PROPERTY." (declare (advertised-calling-convention (project property)) (apply (cl-struct-slot-value 'project 'get inst) xargs)) If you have a project and want to see whether it supports finding C include paths, you'd just use iface-query with 'project-c, and if that succeeds, call (project-c-include-directories my-c-project file). You'd actually *make* interface instances by building an interface struct as you would any other struct and supply closures (e.g., the result of `apply-partially') for the slot values so that you can maintain state (or not) between subsequent calls on the same interface instance. Anyway, all of this would be very lightweight and (I think) resolvable completely at compile time. Note that it's probably not a good idea to go even simpler and have, say, my-git-project inherit from project directly: what if the size of project changes? (Things would break because cl-defstruct accessors hardcode field offsets, and that's a good thing.) What if you want to implement multiple pieces of optional functionality? (Sure, you can make some struct fields nullable, but then you have to provide some way to query whether a field is actually implemented.) Better to just define additional interfaces for optional functionality. The interface approach seems decently light and extensible, and the implementation complexity is low. >>>> +@defun cl-struct-set-slot-value struct-type slot-name inst value >>> We don't need this, since we can always use setf instead. >> So? We have both (setf (aref ...) ...) and (aset ...). >=20 > That's only because (setf (aref ...) ...) needs to macroexpand to somet= hing. > [ It's one of the differences between Common-Lisp and Elisp. ] >=20 > In your case, (setf (cl-struct-slot-value ...) ...) can macroexpand to > something without needing cl-struct-set-slot-value. Actually, in order= > for (incf (cl-struct-slot-value ...)) not to compute the offset twice, > (setf (cl-struct-slot-value ...) ...) will end up expanding to somethin= g > else than a call to cl-struct-set-slot-value. >=20 >> That test was there in cl-check-type. The test doesn't make sense to m= e >> either. We should drop it in both places if we drop it in cl-the. >=20 > Great, let's drop it then. Thanks. Will do. That test never made much sense to me anyway. >>>> +(cl-define-compiler-macro cl-struct-slot-value >>> Please use (declare (compiler-macro ..)). >> Why? In both cases, the compiler macro is written out-of-line and in >> both cases, we just stick the compiler macro on the symbol's plist. >=20 > Because that's the style we use in Elisp. Well, recently. ;-) It wasn't too long ago that the style was to let-bind dozens of variables at the top of huge functions and setq them everywhere. > Note that (declare (compiler-macro ..)) can provide the compiler-macro > "inline" or "out-of-line". Sure, but it'll be really ugly if it's inline and relatively large (as the macros here are). It goes with a trend I've noticed in the APIs you've implemented, though: you seem to prefer having people defun regular functions and combine them in interesting ways (e.g., with advice-add) instead of using top-level definition forms directly (e.g., defadvice). I largely agree with your approach. >=20 >>> I guess this goes back to the earlier question about when/where the u= se >>> for this functionality came up. >> Unless we're using this functionality in generated code where, while t= he >> slot is constant, it's more convenient to use that slot's name than to= >> try to determine the accessor name. >=20 > Ah, so it's for code generated based on cl-struct-slot-info? > Right, that makes sense. --mlaH60sqLUtnQJtksUsreFLBCsJe2fUNO Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQIcBAEBAgAGBQJTVZsNAAoJEMAaIROpHW7IC38P/RGMhWxbYZ3wC8gptNvnpuyI 03N+E20krr+FDoon9hdJv8QxpMkz1OhdGb7RQFrWX+9z9kmxqZIpH/D6oxP34mgd Azsoip2CBU+uB+VX5wpUJFpqVsqmffv1d5E+F/WTco/rBpCoE31ZwD8Zro1wrWyt P/CqvUbrZ5f0X5VHTA5AedOCIzRl+A2odqzVvotVFoH/v44tsBpGaqg3rwQRAY5O u7kpqeFokF2UGOWPj7lLYhVdo3ZrX44fAPgWQQ1fAD4Q1SkWQNFKmW1b3zSIyUyN I83JtozjTNwvGdgRVF/pBlgZaPEE7ECXQLmruYkKsFzE9YO6j1MENbVyVR+hQZOy eRefb8P+Oltp4oeLZpsR0aQ0w+sVEXU8LGuXIq70MgNMGhaQ4uenkO0c8FUQS6BL kfDEKM3nv9xpFIXTJ++Yi17CDSI20EYe54GpKUYyXR1TA1Z4uMgSdOR0741bnQS+ +EWxEtwDQ27R3tQv2TwyfmGesVwwfdvFczEqCSgzR1F88FxdcdHf+kpy6V1P7XZ/ Qyiqam/B0NsDoeDdwA3Dq/6uMSKW/NtrB7hGBPmIas9iZxO6EgHVY9Er2kJFWj5F XUmugqrHMi60SDx2ODzHR0UvLum5IgT3esa1eYD0FZy0UJurIQ2XPTC7+D9QVQU9 pWML3Sec3aSM3anQXtiu =Cgmw -----END PGP SIGNATURE----- --mlaH60sqLUtnQJtksUsreFLBCsJe2fUNO--