From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Andy Wingo Newsgroups: gmane.lisp.guile.user Subject: Re: Simplified slot access in goops Date: Sat, 28 Aug 2010 13:07:04 -0700 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: dough.gmane.org 1283025851 21840 80.91.229.12 (28 Aug 2010 20:04:11 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sat, 28 Aug 2010 20:04:11 +0000 (UTC) Cc: guile-user@gnu.org To: "Maciek Godek" Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Sat Aug 28 22:04:09 2010 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1OpRdF-00085s-Hw for guile-user@m.gmane.org; Sat, 28 Aug 2010 22:04:05 +0200 Original-Received: from localhost ([127.0.0.1]:48661 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OpRdE-0005GJ-US for guile-user@m.gmane.org; Sat, 28 Aug 2010 16:04:04 -0400 Original-Received: from [140.186.70.92] (port=51714 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OpRd6-0005GC-FL for guile-user@gnu.org; Sat, 28 Aug 2010 16:04:00 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OpRd1-0003AC-T1 for guile-user@gnu.org; Sat, 28 Aug 2010 16:03:56 -0400 Original-Received: from a-pb-sasl-quonix.pobox.com ([208.72.237.25]:38425 helo=sasl.smtp.pobox.com) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OpRd1-0003A8-PW for guile-user@gnu.org; Sat, 28 Aug 2010 16:03:51 -0400 Original-Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by a-pb-sasl-quonix.pobox.com (Postfix) with ESMTP id 5007AD19CC; Sat, 28 Aug 2010 16:03:51 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to:cc :subject:references:date:in-reply-to:message-id:mime-version :content-type; s=sasl; bh=aLueqqSw/I/J11RmYqyFM2c8oMc=; b=t/lQX8 ON2Vxqmgp8ECKakfOHXPM28L3Qb1c4EWnJ4X2msdwHsvO4RwCkNZ9kAqpngkhAo6 /MZZw1zrXyEMaK4vOCGAZNbEpbIEUdjbn8mdNCd729GKPg0KSkSPGpxcg8Awiyvy gN1+G63pFLUrA3K6Loz670p8/JjjKzIPosvSg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=pobox.com; h=from:to:cc :subject:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=sasl; b=CnvkOPyzjNBrplxalRWd1FY2VRdVIQBt b0IJirmJPxWRGBrqay/yCWnNnGO76BTefhuRsD7hEhGdATo4kXttHpYbwdXUJ0Rr ScF53aYyDBICqCij0tkKmBwc7lBbRZANcUPbh1lnDsCk0jeBeMaqogMO12AW/cFu zERmR9xNPUg= Original-Received: from a-pb-sasl-quonix. (unknown [127.0.0.1]) by a-pb-sasl-quonix.pobox.com (Postfix) with ESMTP id 3911DD19CB; Sat, 28 Aug 2010 16:03:50 -0400 (EDT) Original-Received: from unquote.localdomain (unknown [75.28.21.123]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by a-pb-sasl-quonix.pobox.com (Postfix) with ESMTPSA id 78CE3D19CA; Sat, 28 Aug 2010 16:03:48 -0400 (EDT) In-Reply-To: (Maciek Godek's message of "Thu, 27 Nov 2008 21:36:30 +0100") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) X-Pobox-Relay-ID: 5FF9E5D4-B2DF-11DF-87D2-030CEE7EF46B-02397024!a-pb-sasl-quonix.pobox.com X-detected-operating-system: by eggs.gnu.org: Solaris 10 (beta) X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:8110 Archived-At: Hi Maciek, I know its been a couple years, but you raised an interesting point that Guile wasn't really able to handle at that point. Your implementation of `in' (commonly known as `with-slots', I believe) follows the mail. On Thu 27 Nov 2008 12:36, "Maciek Godek" writes: > (use-modules (oop goops)) > (use-syntax (ice-9 syncase)) With Guile 2.0 (coming shortly!), there is no more need to use ice-9 syncase. > Now suppose we have an instance of a class: > (define-class C () > a b c) > (define o (make C)) > > Using the "in" macro, we can write: > (in o > (set! a 5) > (set! b (1+ a)) > (set! c (+ a b)) > (+ a b c)) > => 22 The problem with this macro is that `o' can be of any type at all, but Guile needs to know at least whether a given identifier is a macro or a local variable or what, at expansion time. So for that reason, with-slots usually takes a list of slots, explicitly: (with-slots o (a b c) (set! a 5) (set! b (1+ a)) (set! c (+ a b)) (+ a b c)) It would be possible to pass the class instead, but then the class would need to be known at compile-time, and you run into a number of issues there. Anyway, here's that with-slots definition: (define-syntax with-slots (syntax-rules () ((_ obj (slot ...) b b* ...) (let-syntax ((slot (identifier-syntax (id (slot-ref obj 'slot)) ((set! id val) (slot-set! obj 'slot val)))) ...) b b* ...)))) Here we use the new settable identifier-syntax. Note that slot-ref / slot-set isn't the most efficient way to reference slots; the best thing is to use accessors, which JIT-compile (sorta) to struct-ref opcodes, but we don't know that accessors exist for these slots. You can define a with-accessors macro though, that does assume accessors are available. In fact with more assumptions, it's possible to compile to struct-ref / struct-set yourself -- see the examples in the "Syntax" chapter of "The Scheme Programming Language" 4th edition (available online) for an illuminating take on the issue. Cheers, Andy The original definition: > (define-syntax let-alias > (syntax-rules () > ((_ ((id alias) ...) body ...) > (let-syntax ((helper (syntax-rules () > ((_ id ...) (begin body ...))))) > (helper alias ...))))) > > (define slot (make-procedure-with-setter slot-ref slot-set!)) > > (define-syntax in (syntax-rules () > ((_ object expr ...) > (primitive-eval > (list 'let-alias > (map (lambda(s)(list(car s)(list 'slot object (list 'quote (car s))))) > (class-slots (class-of object))) > (quote expr) ...))))) > -- http://wingolog.org/