guile-user
[Top][All Lists]
Advanced

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

read-hash-extend and geiser


From: Panicz Maciej Godek
Subject: read-hash-extend and geiser
Date: Tue, 11 Sep 2012 23:18:23 +0200

Hey,
I've been fighting to make vectors, hash tables and objects
usable from scheme level. I therefore came up with a common
interfacing method to those objects:

(define (getter obj key)
  (cond ((vector? obj)
         (vector-ref obj key))
        ((hash-table? obj)
         (hash-ref obj key))
        ((instance? obj)
         (slot-ref obj key))))

(define (setter obj key value)
  (cond ((vector? obj)
         (vector-set! obj key value))
        ((hash-table? obj)
         (hash-set! obj key value))
        ((instance? obj)
         (slot-set! obj key value))))

(define ref (make-procedure-with-setter getter setter))

so that instead of (vector-ref v 0) one can now write (ref v 0).
This is still lame, though, so I decided to make use of the
infamous read-hash-extend, to write #[v 0] instead.

I quickly wrote a function to support the new syntax, with
no error detection, namely:
(read-hash-extend #\[
                  (lambda (char port)
                    (let* ((exp `(ref ,(read port) ,(read port))))
                      (catch 'read-error (lambda()(read port))
(lambda(key . args) key))
                      exp)))

To my surprise, I was able to evaluate the code containing
this new syntax in emacs/geiser
(define v #(1 2 3))
#[v 0] ;C-xC-e => 1
(set! #[v 0] 20)
v ; => #(20 2 3)

My conscience, however, was deeply dissatisfied with this code,
so I wrote a more decent equivalent:

(read-hash-extend #\[
                  (let ((process (match-lambda
                                  ((object key)
                                   `(ref ,object ,key))
                                  (default
                                    default))))
                    (lambda (char port)
                      (let loop ((exp '()))
                        (let ((char (peek-char port)))
                          (cond ((char-whitespace? char)
                                 (read-char port)
                                 (loop exp))
                                ((eq? char #\])
                                 (process (reverse exp)))
                                (#t
                                 (loop (cons (read port) exp)))))))))

To my bigger surprise, this code could not be evaluated in emacs/geiser
in a traditional way, but when invoked using eval and wrapped in string, like
(primitive-eval (with-input-from-string "#[v #[v 0]]" read))
it worked just as expected.

Does anyone of you know what could be the source of the
difference?

BTW I don't know how legitimate it is to use the read-hash-extend modification.
I remember that guile 1.4 had an infixed module, but I see that it is no longer
shipped with the package. Could anyone tell, why?

Best regards,
M.



reply via email to

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