i've got this ready to be pushed and i suggest this for inclusion and/or discussion:
(defun concatenate-symbol (&rest args) "A DWIM symbol concatenate: Args will be converted to string and be concatenated to form the resulting symbol with one exception: when a package is encountered then it is stored as the target package to use at intern. If there was no package among the args then the symbol-package of the first symbol encountered will be used. If there are neither packages nor symbols among the args then the result will be interned into the current package at the time of calling." (let* ((package nil) (symbol-name (string-upcase (with-output-to-string (str) (dolist (arg args) (typecase arg (string (write-string arg str)) (package (setf package arg)) (symbol (unless package (setf package (symbol-package arg))) (write-string (symbol-name arg) str)) (integer (write-string (princ-to-string arg) str)) (character (write-char arg) str) (t (error "Cannot convert argument ~S to symbol" arg)))))))) (if package (intern symbol-name package) (intern symbol-name))))
"Attila Lendvai" attila.lendvai@gmail.com writes:
i've got this ready to be pushed and i suggest this for inclusion and/or discussion:
(defun concatenate-symbol (&rest args) "A DWIM symbol concatenate: Args will be converted to string and be concatenated to form the resulting symbol with one exception: when a package is encountered then it is stored as the target package to use at intern. If there was no package among the args then the symbol-package of the first symbol encountered will be used. If there are neither packages nor symbols among the args then the result will be interned into the current package at the time of calling."
I'd like it better as
(concatenate-symbol package-designator &rest string-designators)
where T as package is equivalent to *package*, and NIL means to create an uninterned symbol, or
(concatenate-symbol package-or-string-designator &rest string-designators)
where the first argument can either be the package to intern in. In any case, having an optional package /somewhere/ among the arguments seems a bit arbitrary.
..but then again, I've been pretty happy with FORMAT-SYMBOL, so maybe my use-cases are different.
Cheers,
-- Nikodemus Schemer: "Buddha is small, clean, and serious." Lispnik: "Buddha is big, has hairy armpits, and laughs."
Nikodemus Siivola nikodemus@random-state.net writes:
"Attila Lendvai" attila.lendvai@gmail.com writes:
i've got this ready to be pushed and i suggest this for inclusion and/or discussion:
(defun concatenate-symbol (&rest args) "A DWIM symbol concatenate: Args will be converted to string and be concatenated to form the resulting symbol with one exception: when a package is encountered then it is stored as the target package to use at intern. If there was no package among the args then the symbol-package of the first symbol encountered will be used. If there are neither packages nor symbols among the args then the result will be interned into the current package at the time of calling."
Here's my take:
(defun concatenate-symbol (package &rest arguments) "Returns a symbol whose name is a concatenation of printed representations of ARGUMENTS, printed as if by PRINC. If PACKAGE is NIL, the symbol is a fresh uninterned symbol. If PACKAGE is T, the symbol is interned in the current package. Otherwise the symbol is interned in the package designated by PACKAGE." (let ((name (with-output-to-string (s) (dolist (part arguments) (princ part s))))) (if package (intern name (if (eq t package) *package* package)) (make-symbol name))))
I'm a still bit non-plussed of when
(concatenate-symbol pkg "FOO-" (incf *my-counter* i) "-DING-" i "-" tail)
would be preferable to
(format-symbol pkg "FOO-~D-DING-~D-~A" (incf *my-counter* i) i tail)
...so I assume I am misunderstanding the typical use-cases.
Cheers,
-- Nikodemus Schemer: "Buddha is small, clean, and serious." Lispnik: "Buddha is big, has hairy armpits, and laughs."
Here's my take:
(defun concatenate-symbol (package &rest arguments) "Returns a symbol whose name is a concatenation of printed representations of ARGUMENTS, printed as if by PRINC. If PACKAGE is NIL, the symbol is a fresh uninterned symbol. If PACKAGE is T, the symbol is interned in the current package. Otherwise the symbol is interned in the package designated by PACKAGE." (let ((name (with-output-to-string (s) (dolist (part arguments) (princ part s))))) (if package (intern name (if (eq t package) *package* package)) (make-symbol name))))
I'm a still bit non-plussed of when
(concatenate-symbol pkg "FOO-" (incf *my-counter* i) "-DING-" i "-" tail)
would be preferable to
(format-symbol pkg "FOO-~D-DING-~D-~A" (incf *my-counter* i) i tail)
...so I assume I am misunderstanding the typical use-cases.
well, the point in my original proposal was to cover most of the (my?) common usecases with a dwim function that is intuitive and easy to read:
(concatenate-symbol "FOO" some-symbol "BAR")
therefore adding the package argument makes it kinda pointless, we should just use format-symbol then. also another requirement that often comes up for me is to be able to control what should happen if the symbol already exists and it was not interned by us. i usually (setf (get symbol 'some-marker-that-it-was-created-by-us) t) and later check that when the interning is requested again.
all in all, the more i'm thinking about it, the less suitable i find it in alexandria. i guess people should just roll their own macros for specific use-cases or use format-symbol.
On 11/20/06, Nikodemus Siivola nikodemus@random-state.net wrote:
(concatenate-symbol pkg "FOO-" (incf *my-counter* i) "-DING-" i "-" tail) would be preferable to (format-symbol pkg "FOO-~D-DING-~D-~A" (incf *my-counter* i) i tail)
FWIW, in my limited experience, I prefer concatenate-symbol (though I've grown fond of SBCL's name symbolicate :)) because I can more easily cater to the so-called "modern" lisps:
(symbolicate '#:foo- (incf *my-counter* i) '#:-ding- i "-" tail)
With format-symbol, the control string would only add noise.
alexandria-devel@common-lisp.net