From: Evyn
Subject: Appending to same list
Date: 
Message-ID: <1179741337.752094.256880@z28g2000prd.googlegroups.com>
Hi all,

Total Lisp newbie here with a question.

I am trying to write a function that accepts input and appends it to a
list, then prints that list. I can write all the necessary code
seperatly, but appending to the same list just isn't working.

For example, I'd like to be able to enter "c", "a" and "t" on seperate
input lines and have the function print "c", then "ca" then "cat"...

Here is what I have been playing with:

(defun app-list ()
	(setq l '(a))
	(loop do
		(format t "~%Enter datum: ")
		(setf dm (read))
		(append l '(dm))
		(princ l)
	while(not (equal dm 'quit))
	)
)

Thanks for your time.
Evyn

From: Timofei Shatrov
Subject: Re: Appending to same list
Date: 
Message-ID: <4651746a.16798915@news.readfreenews.net>
On 21 May 2007 02:55:37 -0700, Evyn <·············@gmail.com> tried to confuse
everyone with this message:

>Hi all,
>
>Total Lisp newbie here with a question.
>
>I am trying to write a function that accepts input and appends it to a
>list, then prints that list. I can write all the necessary code
>seperatly, but appending to the same list just isn't working.
>
>For example, I'd like to be able to enter "c", "a" and "t" on seperate
>input lines and have the function print "c", then "ca" then "cat"...

That's string concatenation which has little to do with appending lists. Lists
are not strings and symbols are not characters. But whatever...

>Here is what I have been playing with:
>
>(defun app-list ()
>	(setq l '(a))
I'm at loss what the purpose of that line is. Empty list is called NIL.

>	(loop do
>		(format t "~%Enter datum: ")
>		(setf dm (read))
>		(append l '(dm))
I guess you want to make a list out of dm here (what is "dm", anyway, you've got
to use more descriptive names for variables). '(dm) is not a good substitution
for (list dm) in that case. Quoting prevents all evaluation, so Lisp won't see
the value of dm. You're basically appending the symbol DM instead of it's value.

>		(princ l)
>	while(not (equal dm 'quit))
>	)
>)

Your indentation is quite strange, which hints at the fact that you're using
non-Lisp aware editor. Good editor should be able to match parentheses and
indent your code properly. Emacs is one possibility, you may want to check it
out.

-- 
|Don't believe this - you're not worthless              ,gr---------.ru
|It's us against millions and we can't take them all... |  ue     il   |
|But we can take them on!                               |     @ma      |
|                       (A Wilhelm Scream - The Rip)    |______________|
From: Rainer Joswig
Subject: Re: Appending to same list
Date: 
Message-ID: <joswig-D1E2E1.12192621052007@news-europe.giganews.com>
In article <························@z28g2000prd.googlegroups.com>,
 Evyn <·············@gmail.com> wrote:

> Hi all,
> 
> Total Lisp newbie here with a question.
> 
> I am trying to write a function that accepts input and appends it to a
> list, then prints that list. I can write all the necessary code
> seperatly, but appending to the same list just isn't working.
> 
> For example, I'd like to be able to enter "c", "a" and "t" on seperate
> input lines and have the function print "c", then "ca" then "cat"...
> 
> Here is what I have been playing with:
> 
> (defun app-list ()
> 	(setq l '(a))
> 	(loop do
> 		(format t "~%Enter datum: ")
> 		(setf dm (read))
> 		(append l '(dm))
> 		(princ l)
> 	while(not (equal dm 'quit))
> 	)
> )
> 
> Thanks for your time.
> Evyn

First you need to introduce a local variable for your list.
This can be done with LET.
You need also a variable for your input. LET again.
APPEND has no side effect, you need to save the result
of APPEND somewhere in the LOOP.


This is an example here. It prints the list not
in the order you want, but that is an exercise for you. ;-)

(defun app-list ()
  (let ((list '())
        (input nil))
    (loop do
          (format t "~%Enter datum: ")
          (setf input (read))
          while (not (eq  input 'quit))
          do
          (push input list)
          (princ list))
    list))

-- 
http://lispm.dyndns.org
From: Pascal Bourguignon
Subject: Re: Appending to same list
Date: 
Message-ID: <87wsz2xxlq.fsf@thalassa.lan.informatimago.com>
Evyn <·············@gmail.com> writes:

> Hi all,
>
> Total Lisp newbie here with a question.
>
> I am trying to write a function that accepts input and appends it to a
> list, then prints that list. I can write all the necessary code
> seperatly, but appending to the same list just isn't working.
>
> For example, I'd like to be able to enter "c", "a" and "t" on seperate
> input lines and have the function print "c", then "ca" then "cat"...
>
> Here is what I have been playing with:
>
> (defun app-list ()
> 	(setq l '(a))

'(a) returns a literal, read-only, list. You cannot modify such a list.

> 	(loop do
> 		(format t "~%Enter datum: ")
> 		(setf dm (read))
> 		(append l '(dm))

APPEND is a pure function.  It doesn't modify any of its arguments.
You're not using the result, so the compiler just remove this
expressions as dead code.

> 		(princ l)
> 	while(not (equal dm 'quit))
> 	)
> )

Don't put parentheses on their own!  They ARE NOT significant!


I fail to see the relationship between "c", "a", "t", "cat" and lists.
"c", "a", "t", and "cat" are STRINGs!

Well, strings are vectors and both vectors and lists are sequences, so
using only sequence functions, one can write a program that work as
well with both types:

(defparameter *seq-type* 'list) ; or: 'vector

(defun read-seq-of-data ()
 (let ((seq (coerce nil *seq-type*)))
   (loop 
      :do
      (format *query-io* "~%Enter datum: ")
      (finish-output *query-io*)
      (let ((dm (let ((*read-eval* nil)
                      (*package* #.*package*))
                   (read *query-io* nil 'quit))))
         (when (eql dm 'quit)
            (loop-finish))
         (setf seq (concatenate *seq-type* seq (list dm)))
         (princ seq) (terpri)))
   seq))


S/CL-USER[25]> (read-seq-of-data)

Enter datum: abc
(ABC)

Enter datum: "def"
(ABC def)

Enter datum: 123
(ABC def 123)

Enter datum: (a "b" 3)
(ABC def 123 (A b 3))

Enter datum: quit
(ABC "def" 123 (A "b" 3))

S/CL-USER[26]> (setf *seq-type* 'vector)

VECTOR

S/CL-USER[27]> (read-seq-of-data)

Enter datum: abc
#(ABC)

Enter datum: "abc"
#(ABC abc)

Enter datum: 123
#(ABC abc 123)

Enter datum: (a "b" 3)
#(ABC abc 123 (A b 3))

Enter datum: quit
#(ABC "abc" 123 (A "b" 3))

S/CL-USER[28]> 


APPEND works only on lists.  CONCATENATE is the equivalent function
working on sequences.  Both are pure functions, not modifying their
arguments, and returning a new sequence (or only list in the case of
APPEND).

For lists, we could modify them, on the condition the list is not a
literal list, but a list consed at run-time, using NCONC instead of
APPEND.   

For vectors, we could modify them too, on the condition the vector is
adjustable, and if it also has a fill pointer, simply enough using
VECTOR-PUSH-EXTEND.


Now if we wanted to use a STRING, we would have to convert the data
read into a string, and a string being a vector, we would have the
same choices as for other vectors, but in addition, we could use I/O
primitives to build the string, using WITH-OUTPUT-TO-STRING.  But we
cannot get the accumulated string without resetting it, so we can use
with-output-to-string only if we don't need to print the accumulated
string so far:


(defun read-seq-of-data-as-string ()
 (with-output-to-string (res)
   (loop 
      :do
      (format *query-io* "~%Enter datum: ")
      (finish-output *query-io*)
      (let ((dm (let ((*read-eval* nil)
                      (*package* #.*package*))
                   (read *query-io* nil 'quit))))
         (when (eql dm 'quit)
            (loop-finish))
         (princ dm res)))))


C/USER[474]> (READ-SEQ-OF-DATA-AS-STRING)

Enter datum: abc

Enter datum: "def"

Enter datum: 123

Enter datum: (a "b" 3)

Enter datum: quit
"ABCdef123(A b 3)"
C/USER[475]> 



So instead we'll make an adjutable vector and write to it, but using
FORMAT, which is able to write to adjustable/fill-pointered strings:


(defun read-seq-of-data-as-string ()
 (let ((res (make-array 0 :element-type 'character
                  :adjustable t :fill-pointer 0)))
   (loop 
      :do
      (format *query-io* "~%Enter datum: ")
      (finish-output *query-io*)
      (let ((dm (let ((*read-eval* nil)
                      (*package* #.*package*))
                   (read *query-io* nil 'quit))))
         (when (eql dm 'quit)
            (loop-finish))
         (format res "~A" dm)
         (princ res) (terpri)))
   res))



C/USER[479]> (READ-SEQ-OF-DATA-AS-STRING)

Enter datum: abc
ABC

Enter datum: "def"
ABCdef

Enter datum: 123
ABCdef123

Enter datum: (a "b" 3)
ABCdef123(A b 3)

Enter datum: quit
"ABCdef123(A b 3)"
C/USER[480]> 



The secret of course, is to read CLHS:
http://www.lispworks.com/documentation/HyperSpec/Front/Contents.htm   

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
From: Evyn
Subject: Re: Appending to same list
Date: 
Message-ID: <1179744978.805135.47730@b40g2000prd.googlegroups.com>
Thanks for the help.
From: Jens Teich
Subject: Re: Appending to same list
Date: 
Message-ID: <f2s5r8$t6g$01$1@news.t-online.com>
Evyn wrote:
> Hi all,
>
> Total Lisp newbie here with a question.
>
> I am trying to write a function that accepts input and appends it to a
> list, then prints that list. I can write all the necessary code
> seperatly, but appending to the same list just isn't working.

Assuming you mean string, not list.

> For example, I'd like to be able to enter "c", "a" and "t" on seperate
> input lines and have the function print "c", then "ca" then "cat"...

CL-USER 36 > (let ((result-string nil)
                   (input-character nil))
               (loop until (eq input-character #\:) do
                     (setq input-character (read-char))
                     (setq result-string
                           (concatenate 'string
                                        result-string
                                        (format nil "~c" input-character)))
                     (print result-string)))
T
"T" o
"To"
"To " b
"To b" e
"To be"
"To be " o
"To be o" r
"To be or"
"To be or " n
"To be or n" o
"To be or no" t
"To be or not"
"To be or not " t
"To be or not t" o
"To be or not to"
"To be or not to " b
"To be or not to b" e
"To be or not to be" :
"To be or not to be:"
NIL

CL-USER 37 >

-jens