(let ((name "foo")) (fset (intern name) (lambda (x) (* 2 x))))
(foo 21) ; 42
(intern name) creates a symbol with the given name and adds it to the list of accessible symbols (that is what interning means). But if the symbol with that name already exists, it does nothing; just returns the already existing symbol.
(lambda …) creates a function with the given argument list and body.
Addendum: It may be more appropriate to use
fset. See the manual for more on this:
The proper place to use defalias is where a specific function name is being defined—especially where that name appears explicitly in the source file being loaded. This is because defalias records which file defined the function, just like defun (see Unloading).
By contrast, in programs that manipulate function definitions for other purposes, it is better to use fset, which does not keep such records. See Function Cells.