[racket] identifier used out of context error when making my own object-copy

From: Alexander D. Knauth (alexander at knauth.org)
Date: Fri Apr 18 15:53:50 EDT 2014

I’m making my own object-copy macro (just like struct-copy, but for objects), and I am getting this weird error:
. %: identifier used out of context in: %

What am I doing wrong?  And is there another way to do it that doesn’t involve an eval-syntax (I suspect that’s part of the problem)?  

And also, is there another version of field-names that takes a class instead of an object, because I think that will create another problem when I get to the last test (with not-really-chum).  

Here’s the code:
#lang racket/base (require (for-syntax racket/base))

(provide object-copy)

(require racket/class
         (for-syntax
          syntax/parse))

(module+ test
  (require rackunit))

(define-syntax object-copy
  (lambda (stx)
    (syntax-parse stx
      [(object-copy %-expr obj-expr
                    [field-id:id expr:expr]
                    ...)
       #:declare %-expr (expr/c #'class? #:name "class")
       #:declare obj-expr (expr/c #'(is-a?/c %-expr) #:name "object")
       (with-syntax ([ooo '...])
         #'(let* ([% %-expr.c]
                  [obj obj-expr.c]
                  [all-field-syms (field-names obj)]
                  [remaining-field-syms (remove* '(field-id ...) all-field-syms)])
             (with-syntax ([(remaining-field-id ooo) remaining-field-syms])
               (eval-syntax
                #'(new %
                       [field-id expr] ...
                       [remaining-field-id (get-field remaining-field-id obj)] ooo
                       )))))]
      )))

(module+ test
  (define fish%
    (class object% (init-field color weight)
      (super-new) (inspect #f)))
  
  (define marlin (new fish% [color 'orange-and-white] [weight 11]))
  
  (define dory (object-copy fish% marlin
                            [color 'blue]))
  
  (check-equal? dory (new fish% [color 'blue] [weight 11]))
  
  (define shark%
    (class fish% (init-field weeks-since-eating-fish)
      (super-new) (inspect #f)))
  
  (define bruce (new shark% [color 'grey] [weight 110] [weeks-since-eating-fish 3]))
  
  (define chum (object-copy shark% bruce
                            [weight 90]
                            [weeks-since-eating-fish 0]))
  
  (check-equal? chum (new shark% [color 'grey] [weight 90] [weeks-since-eating-fish 0]))
  
  (define not-really-chum
    (object-copy fish% bruce
                 [weight 90]))
  
  (check-equal? not-really-chum (new fish% [color 'grey] [weight 90]))
  
  )


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140418/103dcab7/attachment.html>

Posted on the users mailing list.