0

Currently, I have the following alist:

(define globals '((objects test)))

The name of its variable is stored in another alist:

(define test '((loc globals) (other properties)))

I would like to easily retrieve the objects list in globals. I first tried this code.

(assoc 'objects
       (cadr (assoc 'loc
                    test)))

However, that spit out an error:

ERROR: In procedure assoc: Wrong type argument in position 2 (expecting association list): globals

I searched and found this question, so I tried using eval.

(assoc 'objects
       (eval '(cadr (assoc 'loc
                           test))
             (interaction-environment)))

However, that spit out the same error as above! Does anyone know how to call assoc with the right argument?

EDIT (2014-10-27 21:27 EST): Thank you for all of the solutions. Unfortunately, the submitted examples will likely not work on the full code:

(define-syntax object
  (syntax-rules ()
    ((_ name prop prop* ...)
     (begin
       (define name '(prop prop* ...))
       (let* ((parent (cadr (assoc 'loc name)))
              (objref (cdr (assoc 'objects parent))))
         (set! parent
               (assoc-set! parent
                           'objects
                           (append objref '(name)))))))))

(object my-object 
        (loc globals) 
        (name "Harry") 
        (desc "My Object"))
Community
  • 1
  • 1
Elzair
  • 452
  • 1
  • 4
  • 11

1 Answers1

1

Try this:

(define globals '((objects test)))    
(define test (list (list 'loc globals) '(other properties)))
; alternatively: (define test (list `(loc ,globals) '(other properties)))

(assoc 'objects
       (cadr (assoc 'loc test)))

=> '(objects test)

In this case, we don't want to create a list of symbols such as this:

'(loc globals)

What we want, is a list whose second element is another list called globals:

(list 'loc globals)

Alternatively (as pointed by Chris in the comments) we can use quasiquoting to make explicit that we do want an actual value in the list, not that we forgot to quote an item:

`(loc ,globals)

UPDATE

This is a different problem, you should mention the whole context from the beginning. The assoc-set! procedure is still missing from the question, but you can try this to see if it's what you need:

(define-syntax object
  (syntax-rules ()
    ((_ name prop prop* ...)
     (begin
       (define name '(prop prop* ...))
       (let* ((parent (eval (cadr (assoc 'loc name)))) ; use Guile's eval
              (objref (cdr  (assoc 'objects parent))))
         (set! parent
               (assoc-set! parent
                           'objects
                           (append objref '(name)))))))))
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 1
    I would actually prefer to use quasiquotation in this case (`\`(loc ,globals)`). That way, it's instantly obvious what's getting unquoted (rather than "oh, just something I forgot to quote when using `list`"). – C. K. Young Sep 28 '14 at 01:13
  • I am not sure if this will work for the full code since it uses syntax-rules and requires an arbitrary list for input. Is there some way I can easily rewrite the input list? – Elzair Sep 28 '14 at 01:33
  • @Elzair please check my updated answer. Also notice that the whole syntax rule will return a void value, because the last expression being executed is `set!`, which updates a local binding. I don't know the specifics of what you're trying to implement, but seems like a good moment to reconsider your approach… this looks like an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Óscar López Sep 28 '14 at 01:58
  • Thank you for all your help and your advice. I updated the question with more context. – Elzair Sep 28 '14 at 02:06
  • @ÓscarLópez I am trying to implement an IF-development system similar to http://www.xlisp.org/zil.pdf I am trying to make it easy to define a room (or object) with the following code: (room living-room (loc rooms) (desc "Living Room") (east to kitchen) ....) – Elzair Sep 28 '14 at 02:08
  • @Elzair why macros? see if using a simple procedure (perhaps with a variable number of arguments) is enough to create the data structure that you need, and simply return it at the end (so it can be assigned to a variable, etc.) as it currently stands, that `set!` part isn't doing what you think. why not return `parent`? then you'll be able to assign its value in the calling context. – Óscar López Sep 28 '14 at 02:14