From: WoodHacker
Subject: Strings
Date: 
Message-ID: <1136652851.126270.289710@z14g2000cwz.googlegroups.com>
Now I'm really confused.

I have a function that pads data in a string into columns.  For
instance "aaa  bbb  cccccc".
The function has a temporary valiable called STR that's set to "     ~~
  " in the body of the function.   I then pad and write the string the
way I want.    The string is then returned by the function and set into
the slot value of a class.    Works great - except that the string
retains the value of the previous call to the function.

For instance call one will return "aaa bbb cccccc" - as it should.
But call two will return "xaa yyb zccccc" instead of "x   yy  z"

Why am I unable to clear the temp variable STR by resetting it in the
body of the function?   And that leads to a larger question - what is
the life of values in a LET statement?    Are they renewed with each
call to the function (this seems to be true sometimes and not others -
for instance if I extract a slot-value from a passed class in a LET, I
get the right value, but in the case of my STR variable, if I print it
I see the garbage left over from the prevous call).

If I'm approaching this problem completely wrong, can someone point me
in the right direction?

From: ········@gmail.com
Subject: Re: Strings
Date: 
Message-ID: <1136805363.434198.252390@g44g2000cwa.googlegroups.com>
Edi Weitz wrote:
>Yes, you approach is wrong because you should post your code so we
>can look at it.  Most likely you're modifying a literal constant.

ditto

>I have a function that pads data in a string into columns.  For
>instance "aaa  bbb  cccccc".
>The function has a temporary valiable called STR that's set to "     ~~
>  " in the body of the function.   I then pad and write the string the
>way I want.    The string is then returned by the function and set into
>the slot value of a class.

if your futzing with the length of the string perhaps a stream would be
the way to go

(defvar *buffer* (make-string-output-stream))

(defvar *enough-padding* "          ")

(defun write-with-colmn (string)
  (write-string string *buffer*)
  (write-string (subseq *enough-padding* (length string)) *buffer*))

(defun foo (string)
  (let* ((trimmed (string-left-trim " " string))
	 (next-whitespace (search " " trimmed)))
    (cond ((null next-whitespace) (write-with-colmn trimmed)
	                          (get-output-stream-string *buffer*))
	  (t (write-with-colmn (subseq trimmed 0 next-whitespace))
	     (foo (subseq trimmed next-whitespace)))))

;;;;;;;;;;;;;;;;;;;;;;;;;

FOO> (foo "   this here    string   ")
"this      here      string              "

FOO> (foo "   this      other string")
"this      other     string    "

FOO> (foo "   strings and things!")
"strings   and       things!   "

Nick
From: Edi Weitz
Subject: Re: Strings
Date: 
Message-ID: <uvewtg652.fsf@agharta.de>
On 8 Jan 2006 09:56:00 -0800, "WoodHacker" <·······@comcast.net> wrote:

> If I'm approaching this problem completely wrong, can someone point
> me in the right direction?

Yes, you approach is wrong because you should post your code so we can
look at it.  Most likely you're modifying a literal constant.

  CL-USER 7 > (defun foo ()
                (let ((string "abcdefghijklmnopqrstuvwxyz")
                      (index (random 26)))
                  (setf (char string index) #\-)
                  string))
  FOO

  CL-USER 8 > (foo)
  "abcdefg-ijklmnopqrstuvwxyz"

  CL-USER 9 > (foo)
  "abcdefg-ijklmnopqrstuvw-yz"

  CL-USER 10 > (foo)
  "a-cdefg-ijklmnopqrstuvw-yz"

  CL-USER 11 > (defun foo ()
                 (let ((string (copy-seq "abcdefghijklmnopqrstuvwxyz"))
                       (index (random 26)))
                   (setf (char string index) #\-)
                   string))
  FOO

  CL-USER 12 > (foo)
  "abcdefghijklm-opqrstuvwxyz"

  CL-USER 13 > (foo)
  "abcdefghijklmnopqrstuvw-yz"

  CL-USER 14 > (foo)
  "abcdefghij-lmnopqrstuvwxyz"

  CL-USER 15 > (foo)
  "abcde-ghijklmnopqrstuvwxyz"

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Thomas A. Russ
Subject: Re: Strings
Date: 
Message-ID: <ymi3bjxia8o.fsf@sevak.isi.edu>
"WoodHacker" <·······@comcast.net> writes:

> 
> Now I'm really confused.
> 
> I have a function that pads data in a string into columns.  For
> instance "aaa  bbb  cccccc".
> The function has a temporary valiable called STR that's set to "     ~~
>   " in the body of the function.   I then pad and write the string the
> way I want.    The string is then returned by the function and set into
> the slot value of a class.    Works great - except that the string
> retains the value of the previous call to the function.

That's because you are modifying the STRING object itself.  Unless you
are creating the string value new each time, for example with a call to
MAKE-STRING, you are most likely modifying the same literal string
object on each call to the program.  That would explain why it retains
the value.  Because the object has been modified, and the LET binding is
to a particular object.

> For instance call one will return "aaa bbb cccccc" - as it should.
> But call two will return "xaa yyb zccccc" instead of "x   yy  z"
> 
> Why am I unable to clear the temp variable STR by resetting it in the
> body of the function?

The variable STR is getting a new binding each time through the
function, but you haven't modified the binding of STR to the string.
You have modified the actual string object.

> And that leads to a larger question - what is
> the life of values in a LET statement?

Values have a lifetime that depends on the references to them.  The
normal BINDINGs established by a LET statement are only accessible
inside the body of the let (ignoring special variables and closures for
the time being).  But the objects to which the variables are bound have
their own indefinite lifetimes.

> Are they renewed with each
> call to the function (this seems to be true sometimes and not others -
> for instance if I extract a slot-value from a passed class in a LET, I
> get the right value, but in the case of my STR variable, if I print it
> I see the garbage left over from the prevous call).
> 
> If I'm approaching this problem completely wrong, can someone point me
> in the right direction?

Well, for starters, I would think that you would want to create new
string objects.  In fact, for your particular problem, I would expect
that taking at look at the Common Lisp FORMAT function will give you a
nice, very easy solution to your problem:

   (format nil "~6A~6A~6A" a b c)

for example:
  (let ((a "aaa")
	(b "bbb")
	(c "cccccc"))
     (format nil "~6A~6A~6A" a b c))

==> "aaa   bbb   cccccc"

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: WoodHacker
Subject: Re: Strings
Date: 
Message-ID: <1137417070.340243.87350@z14g2000cwz.googlegroups.com>
Sorry it's taken me so long to get back on this, but my system has been
in upgrade mode and mostly down...

The answer to this problem turned out to be twofold:

First, the font must be a fixed width font - this is true at the
console and in an X Window.   It it is not, nothing will line up.

Second, format will work, but only if you know how many columns there
are.   If you dont, as in my case, use looping to replace the
characters into the proper position.   And create the string with (str
(make-string width :initial-element #\Space)) for each line.   This
works fine.

Thanks for the help....

Bill

Why do we have all these other languages when there's lisp?
From: Pascal Bourguignon
Subject: Re: Strings
Date: 
Message-ID: <87acdwxh1j.fsf@thalassa.informatimago.com>
"WoodHacker" <·······@comcast.net> writes:

> Sorry it's taken me so long to get back on this, but my system has been
> in upgrade mode and mostly down...
>
> The answer to this problem turned out to be twofold:
>
> First, the font must be a fixed width font - this is true at the
> console and in an X Window.   It it is not, nothing will line up.
>
> Second, format will work, but only if you know how many columns there
> are.   If you dont, as in my case, use looping to replace the
> characters into the proper position.   And create the string with (str
> (make-string width :initial-element #\Space)) for each line.   This
> works fine.

You can use ~VA

   (format t "~VA" width item)


(defun format-columns (column-width column-data)
   (format nil "~{~VA~}" (mapcar (function list) column-width column-data)))

(list (format-columns '(10 4 6 8) '("aaaaaaa" "bb" "cccc" "dddddd"))
      (format-columns '(10 4 6 8) '("aaaa" "bbb" "cc" "dd")))

("aaaaaaa   bb  cccc  dddddd  "
 "aaaa      bbb cc    dd      ")

-- 
From: Thomas A. Russ
Subject: Re: Strings
Date: 
Message-ID: <ymislrmh4r2.fsf@sevak.isi.edu>
"WoodHacker" <·······@comcast.net> writes:

> The answer to this problem turned out to be twofold:
> 
> First, the font must be a fixed width font - this is true at the
> console and in an X Window.   It it is not, nothing will line up.

Of course. :)

> Second, format will work, but only if you know how many columns there
> are.   If you dont, as in my case, use looping to replace the
> characters into the proper position.   And create the string with (str
> (make-string width :initial-element #\Space)) for each line.   This
> works fine.

Well, there are various other FORMAT directives that may help with
that.  
  Some of them involve iteration: ~{
  And there formatting lines:     ~<

And the slightly obscure usage of "v" in place of a numeric argument in
order to set field widths:

   (format nil "~vA" 10 "foo") => "foo       "
   (format nil "~vA"  6 "foo") => "foo   "

Unfortunately, my news system has already expired your original message,
so I've lost the example....


> Thanks for the help....
> 
> Bill
> 
> Why do we have all these other languages when there's lisp?
> 

-- 
Thomas A. Russ,  USC/Information Sciences Institute