Pergunta

I would like to initiate dynamically a hash table with defmethod or defun using one of the arguments to create the name. For instance:

(defun foo (arg)
  (let ((NAME (read-from-string (format nil "\*~S\*" arg))))
    (defparameter NAME (make-hash-table))))

Of course, foo create hash table with the symbol NAME, instead of the value of NAME in let. What can I do to get the value of NAME to create this hash table?

Foi útil?

Solução

General Remarks

  • It is almost always wrong to create global variables in functions.

  • It is also almost always wrong to create new symbols using read-from-string instead of intern.

Use a Macro

What you probably want is

(defmacro def-ht (name)
  (let ((var (intern (concatenate 'string "*" (symbol-name name) "*")
                     (symbol-package name))))
    `(defparameter ,var (make-hash-table))))
(def-ht foo)

Use a Function

You might be able to do it in a function too - by inspecting the macroexpansion of a defparameter form and placing the needed stuff in the function:

(defun make-ht-var (name)
  (let ((var (intern (concatenate 'string "*" (symbol-name name) "*")
                     (symbol-package name))))
    (setf (symbol-value var) (make-hash-table))
    (proclaim (list var 'special))))
(make-ht-var 'foo)

Note that the argument to the function is quoted, but the argument to the macro is not.

Outras dicas

You need to use a macro instead of a function. DEFPARAMETER will bind value of MAKE-HASH-TABLE to the symbol NAME because it evaluates at macro-expansion time which occurs earlier than run-time, which is when the function FOO binds the lexical value of NAME.

Look up the CL evaluation model for a deeper understanding.

(defmacro foo (arg)
  (let ((name (read-from-string (format nil "*~S*" arg))))
    `(defparameter ,name (make-hash-table)))) 

(foo "my-hash")
 => <hash-table 0x121>

*my-hash*
=> <hash-table 0x121>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top