Search code examples
common-lisp

Convert string to function


I have the string "+" and I want to convert this into #'+. Basically I want to map string to the corresponding function i.e. "myfunname" to #'myfunname.


Solution

  • This is almost certainly an XY problem: why are you starting with strings?

    If you do need to turn strings into functions then something like the below will do that and is significantly safer than using read:

    (defun string->function (name &key (readtable-case (readtable-case *readtable*))
                                  (package *package*))
      (let ((effective-name (map 'string
                                 (ecase readtable-case
                                   ((:upcase)
                                    #'char-upcase)
                                   ((:downcase)
                                    #'char-downcase)
                                   ((:preserve)
                                    #'identity)
                                   ((:invert)
                                    (lambda (c)
                                      (cond
                                       ((upper-case-p c)
                                        (char-downcase c))
                                       ((lower-case-p c)
                                        (char-upcase c))
                                       (t c)))))
                                 name)))
        (multiple-value-bind (s status) (find-symbol effective-name package)
          (unless status
            (error "no symbol for ~S (from ~S)" effective-name name))
          (unless (fboundp s)
            (error "no function for ~S (from ~S, originally ~S)" s effective-name name))
          (symbol-function s))))
    

    Now

    > (string->function "+")
    #<Function + 80E004F189>
    
    > (eql (string->function "+") #'+)
    t
    
    > (string->function "string->function")
    #<Function string->function 80200011E9>
    
    > (string->function "unknown")
    
    Error: no symbol for "UNKNOWN" (from "unknown")
    
    > (string->function "*print-case*")
    
    Error: no function for *print-case* (from "*PRINT-CASE*", originally "*print-case*")