I hope I understand your idea right. What's about this?
(defun magically-add (number &optional (base 'test-))
(funcall (intern (concatenate 'string
(symbol-name base)
(write-to-string number)))))
It converts the number as well as the base into a string, concatenates it, then converts it back into a symbol for calling it.
Testing:
CL-USER 1 > (defun test-1 () "hello World")
TEST-1
CL-USER 2 > (magically-add 1)
"hello World"
Note that this holds only for dynamically scoped functions – that means it does not work for functions defined with labels or flet. (For a similar reason why you cannot get the value of a lexical scoped symbol – for more details have a look here) If you want to have that, you can use a macro:
(defmacro magically-add (number &optional (base 'test-))
(list (intern (concatenate 'string
(symbol-name base)
(write-to-string number)))))
Now it works for lexically scoped functions, too:
CL-USER 3 > (flet ((test-1 () "Hello again")) (magically-add 1))
"Hello again"
EDIT:
To answer to your problem after your edit – There two major things wrong.
First, you omitted the number
variable and converted your new variable type
to a string. So you will call a function named test-double
that doesn't exist. Second, you call that function without any arguments. You must add them to the function-call.
Here is a version of magically-add that receives arbitrary number of arguments, but you MUST give the base
variable to it. It doesn't default to test-
anymore. It also uses the DEFUN version because of Rainer Joswigs comment below. Being restricted to only using plain numbers for the number
argument (and not variables and not elements of lists) seems to be a greater inconvenience to me than not using lexically scoped functions.
(defun magically-add (base number &rest args)
(apply (intern (concatenate 'string
(symbol-name base)
(write-to-string number)))
args))
So the first two arguments are for contructing the function name and all the rest arguments used to call this function:
CL-USER 1 > (defun test-1 (foo bar baz) (list foo bar baz))
TEST-1
CL-USER 2 > (magically-add 'test- 1 "hi" 42 'symbol)
("hi" 42 SYMBOL)
If someone has an idea how to do something similar to that with not being restricted to dynamically scoped functions, I'd be interested, too.
EDIT 2:
To answer your second edit: There's quiet few to change to achieve that. write-to-string
gives you a string of the printed representation of number
. Of course, if it's the keyword :double
, you'll get ":DOUBLE"
. You can just use symbol-name
again to retrieve the name of the keyword – which is just "DOUBLE"
.
(defun magically-add (praefix postfix &rest args)
(apply (intern (concatenate 'string
(symbol-name praefix)
"-"
(symbol-name postfix)))
args))