> hello,
>
> in cmulisp i type:
>
> (setq a 'hello)
> (setq b 3)
>
> how can i set a to be the "concatenation" of a and b, i.e. what i would
> write as (setq a 'hello3) ?
>
> i tried (setq a (make-symbol (format nil "~S~S" a b)))
> which gives #:HELLO3
>
> any ideas? it surely is absolutely obvious.
Try intern instead of make-symbol...
--
Raymond Wiker, Orion Systems AS
+47 370 61150
> i tried (setq a (make-symbol (format nil "~S~S" a b)))
> which gives #:HELLO3
That is a symbol which concatenates A and B, you just need to intern
it, using INTERN -- if you want it interned!
However you should also probably write the original code as something
like:
(format nil "~S~S" (symbol-name a) b)
unless you want exciting things to happen if *print-case* is not
:upcase (this is a common gotcha in CL code which makes symbols from
other symbols).
--tim
> the symbol is created in some package, but should have its home in
> another package, "SHARED". other packages using "SHARED" should know the
> newly created symbols too.
> i am thinking about
> intern <symbol> "SHARED" and then
> export <symbol> from within "SHARED" and then I probably have all
> packages using "SHARED" to re-use it??
No, that will just work without stress. Intern it in the package,
then export it (with something like (export (intern ... ...))), then
everyone that uses that package will see the new symbol automagically.
However an error can happen when you do the export if some package
which uses the exporting package has a symbol with the same name.
This should be a continuable error though.
There is a crucial difference between importing a symbol from a
package and merely using the package which may be what is confusing
you: importing a symbol makes the symbol exist directly in the
importing package (as well as the exporting package), using another
package just adds it to the list of packages searched for symbols.
Importing is what you want to do if you want to construct some
interface package (like CL, typically), which doesn't actually have
many symbols of its own, but imports a lot of symbols from other
packages and then reexports them. (This confused me for years, and it
probably still does in fact, so this explanation may be wrong...)
--tim
> with symbol-name i get: |"HELLO"3|
Sorry, my mistake, that should have been:
(format nil "~A~S" (symbol-name ...) ...)
--tim
why do you think you need to "re-use" those packages?
| it seems like being a bad idea creating symbols which are shared over
| packages!?
it might, but that depends on their purpose.
#:Erik
I'm not sure this is really good advice.
we really want to concatenate a few strings to make a new string. format
does a whole bunch of weird stuff that may look right, but the exhaustive
test case is non-trivial to construct, and it really can't be caught any
other way until you know what you're doing with an exceptionally high
level of precision and attention to detail. (since this topic comes up
every once in a while, a search engine hit rate increaser: static typing
-- it won't help at all in such interesting real-life cases.)
a simple mistake like using ~S with symbols involves the *print-case* of
symbols, which, while some people might be happy with the default, will
encounter a user who prefers to see lower-case symbol names, the same way
he writes them, and it bombs in ways mysterious to the uninitiate.
a simple mistake like using ~S with numbers involves the *print-base* of
numbers, and if the programmer has the skills to set *print-radix* to
true while using non-standard read bases, its effects intervene, too.
(let ((*print-case* :downcase)
(*print-base* 3)
(*print-radix* t))
(format nil "~S~S" 'hello 3))
=> "hello#3r10"
format is exceptionally good at producing output suitable for humans. it
is not very good at producing values suitable for the Lisp reader, yet it
is so often called upon to do that it hurts. here's a different solution
that uses the proper tools for the job, in my usual, unhumble opinion:
(with-output-to-string (*standard-output*)
(with-standard-io-syntax
(prin1 'hello)
(prin1 3)))
=> "HELLO3"
an "optimized" solution suitable for direct consumption for intern, which
is what's really sought in this case:
(concatenate 'string
(symbol-name 'hello)
(with-standard-io-syntax
(write-to-string 3)))
=> "HELLO3"
this might look less convenient than the wrong format solution, but
that's why we have defun. constructing a new symbol out of constituent
parts, however that is defined, is (more or less unfortunately) _not_
child's play -- it is a sufficiently specialized task that even "software
pattern" arguments that this should be an idiom fail: it is not something
users are likely to find just one pattern for, and if they find one,
it would probably be just as wrong as the wrong format solution. in
other words, they need to find out how this stuff works, and then apply
that knowledge to their domain _every_ time.
incidentally, this is also one of the reasons I favor WYSIWYG print names
for symbols. all of this symbol-hacking stuff would be _significantly_
simpler with agreement on that principle.
#:Erik
> I'm not sure this is really good advice.
> [and a lot of stuff elided]
I agree with this pretty much. I was just trying to do a minimal
change to get it to even slightly work, and I'd not really noticed
that the number would break things too.
> this might look less convenient than the wrong format solution, but
> that's why we have defun. constructing a new symbol out of constituent
> parts, however that is defined, is (more or less unfortunately) _not_
> child's play -- it is a sufficiently specialized task that even "software
> pattern" arguments that this should be an idiom fail: it is not something
> users are likely to find just one pattern for, and if they find one,
> it would probably be just as wrong as the wrong format solution. in
> other words, they need to find out how this stuff works, and then apply
> that knowledge to their domain _every_ time.
Yes. Several large bodies of Lisp code I use have variously-broken
versions of this kind of thing, and I've come to the conclusion that
the solution is ultimately to look at what each one is trying to do
and make it do that even when things are set `weirdly', and not to try
and generalise any further than that. Using FORMAT is almost never
right.
--tim
[nice explanation snipped]
Erik> incidentally, this is also one of the reasons I favor WYSIWYG print names
Erik> for symbols. all of this symbol-hacking stuff would be _significantly_
Erik> simpler with agreement on that principle.
While I understood the nice explanation snipped out above, could you
explain more fully exactly what you mean by "WYSIWYG print names"?
Ray
symbols whose print names are what you see, i.e., no case conversion
either on input or on output.
please note that I'm no more a fan of upper-case Common Lisp code than
those who gave Common Lisp *print-case* and readtable-case were.
#:Erik
No, it's dynamic (this is Lisp!).
--tim
as I suspected, but I am curious, from an educational vantage point --
it's an odd assumption to make, in my view, and I wonder how you came to
think this way. here's how I think: when you let a package use another
package, you refer to the package, as opposed to the symbols of the
package with, say, a use-package-symbols operator, which is what import
does, essentially. my goal is to find out how to explain the difference
between import and use-package very succinctly. it is not enough to
argue that the name "use-package" is sufficient, unless one also argues
that people pay _real_ good attention to the names, but whether that is
feasible or not is the underlying concern.
#:Erik
> my goal is to find out how to explain the difference
> between import and use-package very succinctly.
>
> #:Erik
I'm not sure there is a very succinct description. To really
understand the difference I think you have to have a fairly complete
model of how the package system works.
--
~jrm