Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6070757
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T09:58:11+00:00 2026-05-23T09:58:11+00:00

I am building a mechanism to take an arbitrary CLOS object and return a

  • 0

I am building a mechanism to take an arbitrary CLOS object and return a hash from it (useful in my debugging experience).

However, I am not sure how to force a variable expansion. I sense that the solution lies with a correct use of gensym, but I’m not sure how.

;;helper macro
(defun class-slots-symbols (class-name)
  "Returns a list of the symbols used in the class slots"
  (mapcar 'closer-mop:slot-definition-name
      (closer-mop:class-slots
       (find-class class-name))))

;;macro that I am having difficulty with
(defmacro obj-to-hash (obj-inst)
  "Reads an object, reflects over its slots, and returns a hash table of them"
  `(let ((new-hash (make-hash-table))
    (slot-list (class-slots-symbols (type-of ,obj-inst))))

    ;;The slot-list needs to expand out correctly in the with-slots form
    (with-slots (slot-list) obj-inst
       (loop for slot in slot-list do   ;and also here
        (format t "~a~&" slot)
        (hashset new-hash (string slot) slot)))))

After a macroexpand-1, I find that that this expands into the following code (*bar* is a class object):

(macroexpand-1 '(obj-to-hash *bar*))

LET ((NEW-HASH (MAKE-HASH-TABLE))
      (SLOT-LIST (CLASS-SLOTS-SYMBOLS (TYPE-OF *BAR*))))
  (WITH-SLOTS (SLOT-LIST)  ;; <-- this needs to be expanded to *bar*'s slots
      *BAR*
    (LOOP FOR SLOT IN SLOT-LIST ;;<-- not so important
          DO (FORMAT T "~a~&" SLOT) (HASHSET NEW-HASH (STRING SLOT) SLOT))))

Obviously, the problem is that slot-list is not being expanded. Less obvious (to me) is the solution.


Followup: After Rainer pointed me in the right direction:

(defun class-slots-symbols (class-instance)
  "Returns a list of the symbols used in the class slots"
  (mapcar 'closer-mop:slot-definition-name
      (closer-mop:class-slots
       (class-of class-instance))))

(defun object-to-hash (obj)
  "Reflects over the slots of `obj`, and returns a hash table mapping
slots to their values"
  (let ((new-hash (make-hash-table))
    (slot-list (class-slots-symbols obj)))
    (loop for slot in slot-list do
     (hashset new-hash (string slot) 
          (slot-value  obj slot)))
    new-hash))
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T09:58:11+00:00Added an answer on May 23, 2026 at 9:58 am

    Just looking at it I can see no reason why this should be a macro. Rewriting it as a function will save you a lot of trouble.

    The use of WITH-SLOTS is not possible they way you try it. The object is not known in general until runtime. The compiler needs to know the slots of the object at compile time already. You need to use SLOT-VALUE and look up the slot value at runtime.

    You are thinking in many ways too complicated and your code is slightly confused. You can get rid of some confusion by following simple rules and avoiding some wording.

    Let’s look at your code:

    First, it is not a helper macro, since what follows is a function.

    ;;helper macro
    (defun class-slots-symbols (class-name)
    

    Why take a class name? Why not use the class itself? Classes are first class objects. Write function with obvious interfaces. Elementary functions should work on the basic data types.

      "Returns a list of the symbols used in the class slots"
    

    In the class slots no symbols are used. slots have names, one can get this symbol.

      (mapcar 'closer-mop:slot-definition-name
          (closer-mop:class-slots
           (find-class class-name))))
    

    It is no wonder you have a problem with this macro. It is simply because it should be a function, not a macro. Macros are for source transformation. All you need is a simple computation, so no macro is needed

    ;;macro that I am having difficulty with
    (defmacro obj-to-hash (obj-inst)
    

    Poor wording: obj-inst. Either name it object or instance. Not both.

      "Reads an object, reflects over its slots, and returns a hash table of them"
    

    Poor documentation: you don’t READ anything. Read is an I/O operation and in your code is none. You are talking about an ‘object’, but above you have something like ‘obj-inst’. Why talk about the same thing in two different ways? You may want to document what the hash table actual maps. From which keys to which values?

      `(let ((new-hash (make-hash-table))
    

    new-hash is also a poor name. Basically the thing is a hash-table.

        (slot-list (class-slots-symbols (type-of ,obj-inst))))
    

    Why TYPE-OF and then later in the helper function call FIND-CLASS? Common Lisp has CLASS-OF, which returns the class directly.

        ;;The slot-list needs to expand out correctly in the with-slots form
        (with-slots (slot-list) obj-inst
    

    Above won’t work since WITH-SLOTS expects slot names at compile time, not a slot-list.

           (loop for slot in slot-list do   ;and also here
            (format t "~a~&" slot)
            (hashset new-hash (string slot) slot)
    

    HASHSET is not needed, unless it does something special. The usual way to set values is via SETF. SETF takes the form to read a place and the form to compute a value. That’s all. It works for all kinds of data structures. One never needs to remember again how the writer function looks like (name, parameter list, …).

    ))))
    

    Here is my version:

    Note that I use the package CLOS, you may want to use your package CLOSER-MOP

    (defun class-slots-symbols (class)
      "Returns a list of the symbol names of the class slots"
      (mapcar 'clos:slot-definition-name
              (clos:class-slots class)))
    

    Above is a simple function taking a class and returning the list of slot names.

    Next, we have a simple function, which in this form has been written a million times in Common Lisp:

    (defun object-to-hash (object)
      "returns a hashtable with the object's slots as keys and slot-values as values"
      (let ((hash-table (make-hash-table)))
        (loop for slot-name in (class-slots-symbols (class-of object))
              do (setf (gethash slot-name hash-table)
                       (string (slot-value object slot-name))))
        hash-table))
    

    We can also rewrite it to slightly older style Lisp:

    (defun object-to-hash (object &aux (hash-table (make-hash-table)))
      "returns a hashtable with the object's slots as keys
       and string versions of the slot-values as values"
      (dolist (slot-name (class-slots-symbols (class-of object)) hash-table)
        (setf (gethash slot-name hash-table)
              (string (slot-value object slot-name)))))
    

    Above is much simpler and has the whole confusion about macros, generating code, compile time information vs. runtime, … removed. It is much easier to understand, maintain and debug.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

We are building a system that would benefit greatly from a Distributed Caching mechanism,
I am building a logging mechanism in a web application. Being a Windows man,
Building a Django app on a VPS. I am not very experienced with setting
I'm building a commenting mechanism into an application that allows a programmer/plugin author to
I'm building a complex security mechanism to filter access to objects depending on various
I'm building an iPhone app that, among other things, allows the user to take
We are building a security mechanism in our Android App , for which we
Is there an efficient numpy mechanism to generate an array of values from a
I'm building an error handling mechanism for a C++ application. Right now, I got
I'm initially building an index-like mechanism, read each line of the textfile using getline,

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.