10

I have a big list of global variables that each have their own setup function. My goal is to go through this list, call each item's setup function, and generate some stats on the data loaded in the matching variable. However, what I'm trying now isn't working and I need help to make my program call the setup functions.

The global variables and their setup functions are case-sensitive since this came from XML and is necessary for uniqueness.

The data looks something like this:

'(ABCD ABC\d AB\c\d ...)

and the setup functions look like this:

(defun setup_ABCD...  
(defun setup_ABC\d...

I've tried concatenating them together and turning the resulting string into a function, but this interferes with the namespace of the previously loaded setup function. Here's how I tried to implement that:

(make-symbol (concatenate 'string "setup_" (symbol-name(first '(abc\d)))))

But using funcall on this doesn't work. How can I get a callable function from this?

3
  • If Nowhere man's answer worked, it'd be nice to mark it as accepted by clicking the tick. Commented Nov 17, 2008 at 11:07
  • The namegiving standard in Lisp is to use hyphens, not underscores. Also, the reader uppercases all symbols internally, and the standard is to write them in lower case, so the standard way to call your setup function is setup-abcd. Commented Nov 17, 2008 at 13:00
  • Sorry for the delayed tick! Also the setup fns were written by a non-lisper. I've since loaned him my copy of Norvigs Lisp/AI book. Commented Dec 8, 2008 at 6:01

3 Answers 3

12

It's because MAKE-SYMBOL returns an uninterned symbol. You should use INTERN instead.

Sign up to request clarification or add additional context in comments.

3 Comments

BINGO! I was hoping it would be that simple, Thanks a bunch!
can you give an example to cement this for me, i'm still just a little confused :(
If you do (intern "FOO"), you'll get the same symbol that stores the function defined by (defun foo ()). So (funcall (intern "FOO")) is equivalent to (foo). But when you do (make-symbol "FOO") several times, you'll get several symbols with the same name but not EQ. And none of them is the one created when you do (defun foo ()).
0

I'd either use INTERN or (possibly, you'd have to profile to be 100% sure it's helpful) a helper function that does the string concatenation and the initial find, then caches the result in a hashtable (keyed off the original symbol). That may be faster than a pure INTERN/CONCATENATE solution, would potentially generate less transient garbage, but would probalby end up using more long-term storage.

Something along the lines of:

(defvar *symbol-function-map* (make-hash-table))

(defun lookup-symbol (symbol)
  (or (gethash symbol *symbol-function-map*)
      (let ((function-name (intern (concatenate 'string "setup_" (symbol-name symbol)))))
        (setf (gethash symbol *symbol-function-map*) (symbol-function function-name)))))

If you require the name of the function, rather than the function itself, leave out the call to SYMBOL-FUNCTION.

Comments

0
(funcall (read-from-string (concatenate 'string "setup_" (symbol-name(first '(abc\d))))))  

works too.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.