Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

list to string etc.

957 views
Skip to first unread message

Olmeda Piero

unread,
Nov 27, 1996, 3:00:00 AM11/27/96
to

I have read the examples of "string to list" procedures and after I have
found a working procedure for transforming strings to lists. But how can
I write a procedure with this result (I call it "compress" because this
is the name in the Lisp I was using before, Cambridge Lisp)?
>(compress '(a b c d))
>abcd
I absolutely need this procedure because (I think) it is not possible to
use (or at least would it be difficult) lists as property names. I need
to convert parts of lists into property names.
Thank you very much.
I am working now with Allegro Cl (trial version).
Piero Olmeda

Raffael Cavallaro

unread,
Nov 28, 1996, 3:00:00 AM11/28/96
to

Piero,
I'm just a neophyte Lisp hacker, but this function seems to do what you ask.

The only warning is that it assumes that the portion of the list that you
want to convert to a string consists of characters and/or symbols. If you
want to work with lists that include numbers, you'll have to modify it by
using the function #'format instead of the function #' string.

BTW, if more experienced Lispers think I'm going about this all wrong,
please let me know by email as well, as I may not check in here too often.

Raf

;; function to take a list of characters, a starting index,
;; and an ending index and return a string.
;; note that this will not work with a list including numbers
;; since the function #'string will only convert characters
;; and symbols. If you need to work with lists that include
;; numbers, you should modify this to use the function
;; #'format. This should do what you requested in your
;; post though.

(defun my-compress (a-list start end)
"takes a list of characters, starting and ending indices,
and converts the list to a string."
(let ( (a-string "" ))
(do ((i start (+ i 1)))
((> i end) a-string)
(setf a-string (concatenate 'string a-string (string (nth i
a-list) ))))))

Erik Naggum

unread,
Nov 28, 1996, 3:00:00 AM11/28/96
to

* Olmeda Piero

| I have read the examples of "string to list" procedures and after I have
| found a working procedure for transforming strings to lists. But how can
| I write a procedure with this result (I call it "compress" because this
| is the name in the Lisp I was using before, Cambridge Lisp)?
| >(compress '(a b c d))
| >abcd
| I absolutely need this procedure because (I think) it is not possible to
| use (or at least would it be difficult) lists as property names. I need
| to convert parts of lists into property names.

I think your outlined algorithms look suspicious, but here goes

(format nil "~{~S~}" <list of symbols>)

another variety is

(apply #'concatenate 'string (mapcar #'symbol-name <list of symbols>))

#\Erik
--
Please address private replies, only, to "erik". Junk mail, spam,
stupid flames, courtesy copies, etc, should be sent to "nobody".

Raffael Cavallaro

unread,
Nov 28, 1996, 3:00:00 AM11/28/96
to

BTW, if you want an *uninterned* symbol, use #'make-symbol instead of #'intern:

(make-symbol (format nil "~{~S~}" <list of symbols>))

Raf

Raffael Cavallaro

unread,
Nov 28, 1996, 3:00:00 AM11/28/96
to

In article <30581716...@naggum.no>, Erik Naggum <nob...@naggum.no> wrote:


>
> I think your outlined algorithms look suspicious, but here goes
>
> (format nil "~{~S~}" <list of symbols>)
>
> another variety is
>
> (apply #'concatenate 'string (mapcar #'symbol-name <list of symbols>))
>
> #\Erik


I think Piero actually wanted a symbol, not a string, so Erik's
suggestion, as an argument to #'intern would do it:

(intern (format nil "~{~S~}" <list of symbols>) <&optional package>)

Raf

Olmeda Piero

unread,
Nov 29, 1996, 3:00:00 AM11/29/96
to

I am using now the second option, that is

intern (format nil "~{~S~}" <list of symbols>) <&optional package>)

and it works fine. Thank you very much.
Piero

Thomas A. Russ

unread,
Dec 2, 1996, 3:00:00 AM12/2/96
to

In article <329C99...@tip.nl> Olmeda Piero <piero....@tip.nl> writes:

> From: Olmeda Piero <piero....@tip.nl>
> Newsgroups: comp.lang.lisp
>
> I have read the examples of "string to list" procedures and after I have
> found a working procedure for transforming strings to lists. But how can
> I write a procedure with this result (I call it "compress" because this
> is the name in the Lisp I was using before, Cambridge Lisp)?
>>(compress '(a b c d))
>>abcd
> I absolutely need this procedure because (I think) it is not possible to
> use (or at least would it be difficult) lists as property names. I need
> to convert parts of lists into property names.

Using Common Lisp, an alternative to property lists would be to use hash
tables. They can be defined to use the #'equal test and thus have lists
as keys.

> Thank you very much.
> I am working now with Allegro Cl (trial version).
> Piero Olmeda

This should work for you.
--
Thomas A. Russ, USC/Information Sciences Institute t...@isi.edu

Thomas Kaeufl

unread,
Dec 4, 1996, 3:00:00 AM12/4/96
to

Hi,

perhaps the use of PRINC-TO-STRING might be preferred in

> (make-symbol (format nil "~{~S~}" <list of symbols>))

or

> (intern (format nil "~{~S~}" <list of symbols>))

In Lisp always use the function which is just appropriate for your
task. FORMAT is to big.

Thomas Kaeufl
kae...@ira.uka.de


Erik Naggum

unread,
Dec 4, 1996, 3:00:00 AM12/4/96
to

* Thomas Kaeufl

| perhaps the use of PRINC-TO-STRING might be preferred in
|
| > (make-symbol (format nil "~{~S~}" <list of symbols>))
|
| or
|
| > (intern (format nil "~{~S~}" <list of symbols>))
|
| In Lisp always use the function which is just appropriate for your
| task. FORMAT is to big.

using this argument, we should be using C or assembly language.

`format' is a lot more efficient than the uninitiated believe.

if performance is your pet peeve, the `formatter' function parses the
control string normally to `format' and returns a function that can be used
in place of the control string, in which case `format' only calls that
function. this function will be compiled if you stuff it in a variable:

(defvar *symbol-list-formatter* (formatter "~{~S~}"))

... (format t *symbol-list-formatter* <list of symbols>) ...

e.g., I get this from Bruno Haible's CLISP. (I couldn't get CMUCL to want
to print the whole function it generated -- apparently *print-level* is
bound to some ridiculously low value when printing the internals of an
unprintable object of the interpreted-function persuasion. suggestions?)

(formatter "~{~S~}")
=> #<closure :lambda (stream #:arg686 &rest #:args680)
(declare (ignorable stream))
(declare (ignorable #:arg686 #:args680))
(apply
#'(lambda (&rest #:args685)
(declare (ignorable #:args685))
(block nil
(tagbody
system::l
(when (endp #:args685) (return))
(prin1 (pop #:args685) stream)
(go system::l))))
#:arg686)
#:args680>

this is the code that `format' actually runs.

however, if you wanted a version that didn't use `format' and could only be
used with symbols whose names are exactly one character long, this would be
"better":

(map 'string (lambda (symbol) (char (symbol-name symbol) 0))
<list of symbols>)

as I had confirmed recently, the chance that this produces code that equals
the efficiency of the `format' call with a `formatter'-supplied function is
high.

Bob Riemenschneider

unread,
Dec 4, 1996, 3:00:00 AM12/4/96
to

In article <583vl8$7...@nz12.rz.uni-karlsruhe.de> v...@ira.uka.de (Thomas
Kaeufl) writes:

> perhaps the use of PRINC-TO-STRING might be preferred in
>
> > (make-symbol (format nil "~{~S~}" <list of symbols>))
>
> or
>
> > (intern (format nil "~{~S~}" <list of symbols>))
>
> In Lisp always use the function which is just appropriate for your
> task. FORMAT is to big.

I have to disagree with the general principle here. I find that, say,

(format nil "~A.foo" bar)

is usually clearer than

(concatenate 'string bar ".foo")

because it emphasizes the form of the result, which is what I care about,
rather than how it was constructed. For most code one writes, readability
is the most important feature to optimize. (Even when there's a
performance cost, which probably isn't an issue in this case.)

Sure, I'm using an elephant gun to kill a flea, but so what?

-- rar

Stefan k. Bamberger

unread,
Dec 5, 1996, 3:00:00 AM12/5/96
to

In article <583vl8$7...@nz12.rz.uni-karlsruhe.de>, v...@ira.uka.de (Thomas
Kaeufl) wrote:

> Hi,


>
> perhaps the use of PRINC-TO-STRING might be preferred in
>
> > (make-symbol (format nil "~{~S~}" <list of symbols>))
>
> or
>
> > (intern (format nil "~{~S~}" <list of symbols>))
>
> In Lisp always use the function which is just appropriate for your
> task. FORMAT is to big.
>

> Thomas Kaeufl
> kae...@ira.uka.de


I'm not sure why you want to use PRINC-TO-STRING.
If you call it with the whole list it keeps the parantheses in the list,
which is not desired. If you use it to coerce every symbol in the list to
a string it is much more inefficient (in space and time!!) in my LISP
implementation.
Probably there exist other implemantiations which provide a more efficient
implementation of PRINC-TO-STRING

In my MCL 4.0 implementation: (below are the measurements for ACL/w 3.0.1

(time
(dotimes (var 1000)
(apply #'concatenate 'string
(mapcar #'princ-to-string '(a b c d)))
)
)

(Dotimes (Var 1000) (Apply #'Concatenate 'String (Mapcar #'Princ-To-String
'(A B C D)))) took 1,318 milliseconds (1.318 seconds) to run.
Of that, 33 milliseconds (0.033 seconds) were spent in The Cooperative
Multitasking Experience.
296,000 bytes of memory allocated.

---> 1.3 seconds and 296 KB !!!

(time
(dotimes (var 1000)
(format nil "~{~a~}" '(a b c d))
)
)

(Dotimes (Var 1000) (Format Nil "~{~a~}" '(A B C D))) took 612
milliseconds (0.612 seconds) to run.
Of that, 5 milliseconds (0.005 seconds) were spent in The Cooperative
Multitasking Experience.
8,000 bytes of memory allocated.

---> 0.6 seconds and only 8 KB !!!


FORMAT isn't as bad as everybody wants to suggerate

IF you want it more efficient but also with more use of memory - try this:

(time
(dotimes (var 1000)
(apply #'concatenate 'string
(mapcar #'string '(a b c d)))
)
)

(Dotimes (Var 1000) (Apply #'Concatenate 'String (Mapcar #'String '(A B C
D)))) took 86 milliseconds (0.086 seconds) to run.
Of that, 1 milliseconds (0.001 seconds) were spent in The Cooperative
Multitasking Experience.
40,000 bytes of memory allocated.


----> 0.08 seconds and 40 KB !!!

;;;; ****************************

Times in ACL/W 3.0.1 (it's also a slower computer but that's not
interesting as I don't compare the two implemantations....):

You'll see, that the difference between PRINC-TO-STRING and FORMAT is much
smaller but exists. Unfortunately the TIME implementation in ACL don't
report the memory usage :(

PRINC-TO-STRING seems to use a lot of memory as it always has a garbage
collecting additional time whereas the other two don't do garbage
collection

Timing: (DOTIMES (VAR 1000) (APPLY #'CONCATENATE 'STRING (MAPCAR #'STRING
'(A B C D))))
Macro expansion time: 0.00 seconds (0 clock ticks)
Execution time: 0.36 seconds (361 clock ticks)

Timing: (DOTIMES (VAR 1000) (APPLY #'CONCATENATE 'STRING (MAPCAR
#'PRINC-TO-STRING '(A B C D))))
Macro expansion time: 0.00 seconds (0 clock ticks)
Execution time: 2.83 seconds plus 0.49 seconds garbage collecting (2834,
490 clock ticks)

Timing: (DOTIMES (VAR 1000) (FORMAT NIL "~{~a~}" '(A B C D)))
Macro expansion time: 0.00 seconds (0 clock ticks)
Execution time: 2.73 seconds (2734 clock ticks)


-stefan

Cyber Surfer

unread,
Dec 5, 1996, 3:00:00 AM12/5/96
to

In article <tpiv6ic...@violet.csl.sri.com>
r...@violet.csl.sri.com "Bob Riemenschneider" writes:

> I have to disagree with the general principle here. I find that, say,
>
> (format nil "~A.foo" bar)
>
> is usually clearer than
>
> (concatenate 'string bar ".foo")

Why not simply define a function?

(defun (foo-symbol bar)
"convert a symbol to a string, appending \".foo\" on the end"
(concatenate 'string bar ".foo"))

Now you can say (foo-symbol 'futz) and know exactly what you're doing.

> because it emphasizes the form of the result, which is what I care about,
> rather than how it was constructed. For most code one writes, readability
> is the most important feature to optimize. (Even when there's a
> performance cost, which probably isn't an issue in this case.)

There's more than 12 ways of skinning a symbol, in Common Lisp.

> Sure, I'm using an elephant gun to kill a flea, but so what?

Indeed, so what? I agree that conciseness is a good thing. The only
question is "how do we get it?" My experience with Forth tells me
to write lots of short definitions, each of which does something
useful, and hopefully simple enough to find many different uses.
Sometimes a function isn't just a way of re-using some code, but a
way of naming an expression that might otherwise be a little obscure.

Forth encourages programmers to think of definitions as words in a
vocabulary. Some words will be "verbs", while others may be "nouns".
In Lisp, we could perhaps call definitions something different, like
"operators" and "operands". Of course, "verbs" can also be "nouns",
in Forth, and "operators" can also be "operands", in Lisp, so let's
not dwell on this too much!

Perhaps a better name for the foo-symbol function might be symbol->foo,
making it clear that it's a "verb"? I dunno. That's a Scheme convention,
so you might prefer something different in CL.
--
<URL:http://www.enrapture.com/cybes/> You can never browse enough
Future generations are relying on us
It's a world we've made - Incubus
We're living on a knife edge, looking for the ground -- Hawkwind


Thomas Kaeufl

unread,
Dec 6, 1996, 3:00:00 AM12/6/96
to

ba...@informatik.uni-wuerzburg.de (Stefan k. Bamberger) writes

> I'm not sure why you want to use PRINC-TO-STRING.
> If you call it with the whole list it keeps the parantheses in the list,

> which is not desired. ...

After reading older postings of this thread I saw that Stefan is
right. I missed that point. Sorry.

Then, I did his benchmarks in Lucid Common Lisp and got these results

(time
(dotimes (var 1000)
(apply #'concatenate 'string
(mapcar #'princ-to-string '(a b c d)))))

Elapsed Real Time = 1.09 seconds
Total Run Time = 0.75 seconds
User Run Time = 0.70 seconds
System Run Time = 0.05 seconds
Process Page Faults = 120
Dynamic Bytes Consed = 0
Ephemeral Bytes Consed = 148,952

(time
(dotimes (var 1000)
(format nil "~{~a~}" '(a b c d))))

Elapsed Real Time = 1.00 seconds
Total Run Time = 0.88 seconds
User Run Time = 0.87 seconds
System Run Time = 0.01 seconds
Process Page Faults = 105
Dynamic Bytes Consed = 0
Ephemeral Bytes Consed = 60,752


Then, I tested a typical use of PRINC-TO-STRING in the software developed
at our institute and got these results. (The number comes from a counter.)

(time
(dotimes (var 1000)
(concatenate 'string (princ-to-string 'ab) (princ-to-string '!)
(princ-to-string 1))))

Elapsed Real Time = 0.68 seconds
Total Run Time = 0.61 seconds
User Run Time = 0.61 seconds
System Run Time = 0.00 seconds
Process Page Faults = 108
Dynamic Bytes Consed = 0
Ephemeral Bytes Consed = 93,224

(time
(dotimes (var 1000)
(format nil "~{~S~}" (list (princ-to-string 'ab) (princ-to-string '!)
(princ-to-string 1)))))

Elapsed Real Time = 1.25 seconds
Total Run Time = 1.19 seconds
User Run Time = 1.19 seconds
System Run Time = 0.00 seconds
Process Page Faults = 135
Dynamic Bytes Consed = 0
Ephemeral Bytes Consed = 109,416

So, in Lucid PRINC-TO-STRING seems to work more efficient.

There is an old rule of thumb in Lisp: Always use the function which is
just sufficient for your task. Following this guideline the code will
be more clear for the reader. It says exactly what is done. So,
I cannot agree Erik who writes

> using this argument, we should be using C or assembly language.

But now I have the feeling that the discussion leaves the topic of this
thread. I do not know the purpose of converting a list of symbols to
a string. Perhaps it is such that the rule mentioned above should not
be applied?

Thomas Kaeufl
kae...@ira.uka.de

Stefan k. Bamberger

unread,
Dec 10, 1996, 3:00:00 AM12/10/96
to

I cut several lines to save space. I hope I didn't change the semantic.


First of all: I agree with Thomas that one always should use the function
which is just sufficient for one's task. My additional statement is, that
it's not so easy to find it... . A function which is very efficient in a
specific implementation is not worth it in another. And a function (like
format) which looks very complex and time intensive could be very helpful
in certain circumstances.
Especiallly if you write code to run on several (hardware) platforms you
always have to find again and again the different software/implementation
bottlenecks and treat them individually.
It would be a nice addendum to ANSI CL to nail down which function should
be provided more efficient than others to get a better feeling how to
write platform independent FAST code.

In the meanwhile I got a mail from Nat Makarevitch (I didn't see it as a
news so I give a summary here) whichs shows that princ-to-string in CLISP
is faster than format (x3) (tested on LINUX). But even there
PRINC-TO-STRING needs more space.

In article <589br9$l...@nz12.rz.uni-karlsruhe.de>, v...@ira.uka.de (Thomas
Kaeufl) wrote:

[.. lines cut...]

> Then, I did his benchmarks in Lucid Common Lisp and got these results
>
> (time
> (dotimes (var 1000)
> (apply #'concatenate 'string
> (mapcar #'princ-to-string '(a b c d)))))
>

...


> Total Run Time = 0.75 seconds

...


> Ephemeral Bytes Consed = 148,952
>
> (time
> (dotimes (var 1000)
> (format nil "~{~a~}" '(a b c d))))
>

...


> Total Run Time = 0.88 seconds

...


> Ephemeral Bytes Consed = 60,752
>

It looks for me that format is still more (memory) efficient with roughly
the same run time.


>
> Then, I tested a typical use of PRINC-TO-STRING in the software developed
> at our institute and got these results. (The number comes from a counter.)
>
> (time
> (dotimes (var 1000)
> (concatenate 'string (princ-to-string 'ab) (princ-to-string '!)
> (princ-to-string 1))))
>

...


> Total Run Time = 0.61 seconds

...


> Ephemeral Bytes Consed = 93,224
>
> (time
> (dotimes (var 1000)
> (format nil "~{~S~}" (list (princ-to-string 'ab) (princ-to-string '!)
> (princ-to-string 1)))))
>

...


> Total Run Time = 1.19 seconds

...


> Ephemeral Bytes Consed = 109,416
>
> So, in Lucid PRINC-TO-STRING seems to work more efficient.
>

......

Are you sure you compare the same things? In the second example you create
an extra list which you decompose in the format again. Perhaps I miss the
point what you want to demonstrate.

I would write:

(time
(dotimes (var 1000)
(format nil "~a~a~a" 'ab '! 1)))

In my MCL 4.0 version on a power mac.

(Dotimes (Var 1000) (Format Nil "~a~a~a" 'Ab '! 1)) took 382 milliseconds
(0.382 seconds) to run.


8,000 bytes of memory allocated.

against

(Dotimes (Var 1000) (Concatenate 'String (Princ-To-String 'Ab)
(Princ-To-String '!) (Princ-To-String 1))) took 877 milliseconds (0.877
seconds) to run.
200,000 bytes of memory allocated.


- stefan

Thomas Kaeufl

unread,
Dec 12, 1996, 3:00:00 AM12/12/96
to

ba...@informatik.uni-wuerzburg.de (Stefan k. Bamberger) wrote:

> In the second example you create
> an extra list which you decompose in the format again. Perhaps I miss the
> point what you want to demonstrate.

> I would write:

> (time
> (dotimes (var 1000)
> (format nil "~a~a~a" 'ab '! 1)))

Stefan is right. I should have written this call of format too.

After my posting in this group I got a mail from Howard R. Stearns. He writes

> If you want to measure performance of compiled code, than you need to
> compile the code.

So, following his advice I compiled the following functions

(DEFUN GENERATE.CONSTANT (VAR)
(DECLARE (TYPE (OR SYMBOL SYNTAX@TERM) VAR))
(CONCATENATE 'STRING (PRINC-TO-STRING VAR) "!"
(PRINC-TO-STRING
(THE FIXNUM (FUNCALL TEQ=CONSTANT.GENERATOR.COUNTER)))))

(This is our typical application I mentioned. TEQ=CONSTANT.GENERATOR.COUNTER
is a counter.)

(DEFUN MEASURE.PRINC ()
(TIME (DOTIMES (VAR 1000) (GENERATE.CONSTANT 'X))))


(DEFUN GENERATE.CONSTANT.F (VAR)
(DECLARE (TYPE (OR SYMBOL SYNTAX@TERM) VAR))
(FORMAT NIL "~A~A~A" VAR "!"
(THE FIXNUM (FUNCALL TEQ=CONSTANT.GENERATOR.COUNTER))))

(defun measure.format ()
(time (dotimes (var 1000) (GENERATE.CONSTANT.F 'X))))

and obtained the following results:

(MEASURE.PRINC)
Elapsed Real Time = 0.60 seconds
Total Run Time = 0.56 seconds
User Run Time = 0.55 seconds


System Run Time = 0.01 seconds

Process Page Faults = 128


Dynamic Bytes Consed = 0

Ephemeral Bytes Consed = 136,016
NIL

(MEASURE.FORMAT)
Elapsed Real Time = 0.89 seconds


Total Run Time = 0.88 seconds

User Run Time = 0.88 seconds


System Run Time = 0.00 seconds

Process Page Faults = 11


Dynamic Bytes Consed = 0

Ephemeral Bytes Consed = 64,088
NIL


Thomas Kaeufl
kae...@ira.uka.de

0 new messages