manpagez: man pages & more
info guile
Home | html | info | man
[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.5.9 SRFI-10 - Hash-Comma Reader Extension

This SRFI implements a reader extension #,() called hash-comma. It allows the reader to give 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, i.e. #,(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 the program must quote to use it literally, 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 an 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 (see section 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 <BAR> quux") ⇒ "BAR"

#,() is somewhat similar to define-macro (see section 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 (see section Reading Scheme Code), 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 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.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated on February 3, 2012 using texi2html 5.0.

© manpagez.com 2000-2024
Individual documents may contain additional copyright information.