From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Kevin Ryde Newsgroups: gmane.lisp.guile.devel Subject: doc srfi-10 #,() Date: Thu, 02 Sep 2004 09:24:01 +1000 Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Message-ID: <871xhlmv3i.fsf@zip.com.au> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1094081112 30111 80.91.224.253 (1 Sep 2004 23:25:12 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 1 Sep 2004 23:25:12 +0000 (UTC) Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Sep 02 01:25:05 2004 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1C2eTQ-0006xU-00 for ; Thu, 02 Sep 2004 01:25:05 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1C2eYN-0007MH-1R for guile-devel@m.gmane.org; Wed, 01 Sep 2004 19:30:11 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.33) id 1C2eY6-0007LT-Cq for guile-devel@gnu.org; Wed, 01 Sep 2004 19:29:54 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.33) id 1C2eY5-0007KU-6B for guile-devel@gnu.org; Wed, 01 Sep 2004 19:29:54 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1C2eY5-0007KP-45 for guile-devel@gnu.org; Wed, 01 Sep 2004 19:29:53 -0400 Original-Received: from [61.8.0.84] (helo=mailout1.pacific.net.au) by monty-python.gnu.org with esmtp (Exim 4.34) id 1C2eSm-0005R6-Fn for guile-devel@gnu.org; Wed, 01 Sep 2004 19:24:25 -0400 Original-Received: from mailproxy2.pacific.net.au (mailproxy2.pacific.net.au [61.8.0.87]) by mailout1.pacific.net.au (8.12.3/8.12.3/Debian-6.6) with ESMTP id i81NOL4u016360 for ; Thu, 2 Sep 2004 09:24:21 +1000 Original-Received: from localhost (ppp2B3A.dyn.pacific.net.au [61.8.43.58]) by mailproxy2.pacific.net.au (8.12.3/8.12.3/Debian-6.6) with ESMTP id i81NOJ78013443 for ; Thu, 2 Sep 2004 09:24:19 +1000 Original-Received: from gg by localhost with local (Exim 3.36 #1 (Debian)) id 1C2eST-00068C-00; Thu, 02 Sep 2004 09:24:05 +1000 Original-To: guile-devel@gnu.org Mail-Copies-To: never User-Agent: Gnus/5.110003 (No Gnus v0.3) Emacs/21.3 (gnu/linux) X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: main.gmane.org gmane.lisp.guile.devel:4066 X-Report-Spam: http://spam.gmane.org/gmane.lisp.guile.devel:4066 A bit of an expansion of the srfi-10 docs, trying to make the quoting business clearer, and give more examples. 3.1.1 SRFI-10 - Hash-Comma Reader Extension ------------------------------------------- This SRFI implements a reader extension `#,()' called hash-comma. It allows the reader to return new kinds of objects, for use both in data and as constants or literals in source code. This feature is available with (use-modules (srfi srfi-10)) The new read syntax is of the form #,(TAG ARG...) where TAG is a symbol and the ARGs are objects taken as parameters. TAGs are registered with the following procedure. -- Scheme Procedure: define-reader-ctor tag proc Register PROC as the constructor for a hash-comma read syntax starting with symbol TAG, ie. #,(TAG arg...). PROC is called with the given arguments `(PROC arg...)' and the object it returns is the result of the read. For example, a syntax giving a list of N copies of an object. (define-reader-ctor 'repeat (lambda (obj reps) (make-list reps obj))) (display '#,(repeat 99 3)) -| (99 99 99) Notice the quote ' when the #,( ) is used. The `repeat' handler returns a list and for the program to use that literally it must be quoted the same as any other list. Ie. (display '#,(repeat 99 3)) => (display '(99 99 99)) When a handler returns an object which is self-evaluating, like a number or a string, then there's no need for quoting, just as there's no need when giving those directly as literals. For example a simple addition, (define-reader-ctor 'sum (lambda (x y) (+ x y))) (display #,(sum 123 456)) -| 579 A typical use for #,() is to get a read syntax for objects which don't otherwise have one. For example, the following allows a hash table to be given literally, with tags and values, ready for fast lookup. (define-reader-ctor 'hash (lambda elems (let ((table (make-hash-table))) (for-each (lambda (elem) (apply hash-set! table elem)) elems) table))) (define (animal->family animal) (hash-ref '#,(hash ("tiger" "cat") ("lion" "cat") ("wolf" "dog")) animal)) (animal->family "lion") => "cat" Or for example the following is a syntax for a compiled regular expression (*note Regular Expressions::). (use-modules (ice-9 regex)) (define-reader-ctor 'regexp make-regexp) (define (extract-angs str) (let ((match (regexp-exec '#,(regexp "<([A-Z0-9]+)>") str))) (and match (match:substring match 1)))) (extract-angs "foo quux") => "BAR" #,() is somewhat similar to `defmacro' (*note Macros::) in that handler code is run to produce a result, but #,() operates at the read stage, so it can appear in data for `read' (*note Scheme Read::), not just in code to be executed. Because #,() is handled at read-time it has no direct access to variables etc. A symbol in the arguments is just a symbol, not a variable reference. The arguments are essentially constants, though the handler procedure can use them in any complicated way it might want. Once `(srfi srfi-10)' has loaded, #,() is available globally, there's no need to use `(srfi srfi-10)' in later modules. Similarly the tags registered are global and can be used anywhere once registered. There's no attempt to record what previous #,() forms have been seen, if two identical forms occur then two calls are made to the handler procedure. The handler might like to maintain a cache or similar to avoid making copies of large objects, depending on expected usage. In code the best uses of #,() are generally when there's a lot of objects of a particular kind being used as literals or constants. If there's just a few then some local variables and initializers are fine, but that becomes tedious and error prone when there's a lot and the anonymous and compact syntax of #,() is much better. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel