guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: cannot compile: srfi-10 define-reader-ctor 'hash '#,(


From: Ludovic Courtès
Subject: Re: cannot compile: srfi-10 define-reader-ctor 'hash '#,(
Date: Sat, 05 Jul 2014 15:40:47 +0200
User-agent: Gnus/5.130009 (Ma Gnus v0.9) Emacs/24.3 (gnu/linux)

Jan Nieuwenhuizen <address@hidden> skribis:

> (use-modules (srfi srfi-10))
>
> (define-reader-ctor 'hash
>        (lambda elems
>          (let ((table (make-hash-table)))
>            (for-each (lambda (elem)
>                        (apply hash-set! table elem))
>                      elems)
>            table)))

In this example, you want the reader extension to be available at
compile time, and not necessarily at run time.  However, by writing the
code as is, the reader extension is available only at run time, hence
the error.

To require evaluation of the ‘define-reader-ctor’ form at compile time,
change the code to (info "(guile) Eval When"):

--8<---------------cut here---------------start------------->8---
(eval-when (expand)
  (define-reader-ctor 'hash
    (lambda elems
      (let ((table (make-hash-table)))
        (for-each (lambda (elem)
                    (apply hash-set! table elem))
                  elems)
        table))))
--8<---------------cut here---------------end--------------->8---

Now, you’ll get this error:

--8<---------------cut here---------------start------------->8---
$ guile ~/tmp/hash.scm
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /home/ludo/tmp/hash.scm
;;; WARNING: compilation of /home/ludo/tmp/hash.scm failed:
;;; ERROR: build-constant-store: unrecognized object #<hash-table 187ecc0 3/31>
cat
--8<---------------cut here---------------end--------------->8---

The problem here is that the reader extension above returns (at compile
time) a hash table.  However, a hash table as such cannot appear in
source code text, hence the error.

Instead, you’d want the reader extension to return source code that
constructs the hash table.  First, a macro:

--8<---------------cut here---------------start------------->8---
(define-syntax build-hash-table
  (syntax-rules ()
    ((_ table (key value) rest ...)
     (begin
       (hash-set! table key value)
       (build-hash-table table rest ...)))
    ((_ table)
     table)))

(define-syntax-rule (hash-table (key value) ...)
  (let ((table (make-hash-table)))
    (build-hash-table table (key value) ...)))
--8<---------------cut here---------------end--------------->8---

With that macro, we get:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,expand (hash-table ("a" 1) ("b" 2) ("c" 3))
$2 = (let ((table (make-hash-table)))
  (hash-set! table "a" 1)
  (begin
    (hash-set! table "b" 2)
    (begin (hash-set! table "c" 3) table)))
--8<---------------cut here---------------end--------------->8---

Now, if in addition you want #, syntax for that, you can write:

--8<---------------cut here---------------start------------->8---
(eval-when (expand)
  (define-reader-ctor 'hash
    (lambda elems
      `(hash-table ,@elems))))

(define (animal->family animal)
  (hash-ref #,(hash ("tiger" "cat")
                    ("lion"  "cat")
                    ("wolf"  "dog"))
            animal))

(display (animal->family "lion"))
(newline)
--8<---------------cut here---------------end--------------->8---

But I’m not sure the #, extension is worthwhile here.

HTH,
Ludo’.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]