Reading In text file.

Discussion of Common Lisp
Mercenary85
Posts: 10
Joined: Tue Apr 06, 2010 9:56 pm

Reading In text file.

Post by Mercenary85 » Tue Apr 06, 2010 10:04 pm

Hi All im new to the site. Having a bit of a problem, im pretty new to lisp but I've been trying to learn it just as something to experiment with for fun :)


Anyways Im trying to figure out how to read in data and store it as kinda a global parameter.

Like for instance (dunno if I can do this)

Code: Select all

(defparameter *imalist* (list))
So that would define a blank list

and then I would read data from "mydata.txt"
which contains various numbers.

I found something on google, but it didnt actually store the data in anything. I'd prefer to store it in a list.....but everything i've found doesn't keep it in a variable.
then I can do stuff with *imalist* but now after I read in the data *imalist* would be a list with a bunch of numbers in it. Then Im gonna do some math calculations on the list (but thats for another day) the main problem I have right now is Storing them into a list (because I have the function done that calculates the average of the *imalist* right now)

Appreciate everyones help

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: Reading In text file.

Post by gugamilare » Wed Apr 07, 2010 5:09 am

To change the value of a variable, use setf. Like this:

Code: Select all

(defun read-integers-from-file (file)
  ;; reads file and returns a list with the integers inside it
  ...)

(defparameter *imalist* (list))

(setf *imalist* (read-integers-from-file "/path/to/mydata.txt"))

Jasper
Posts: 209
Joined: Fri Oct 10, 2008 8:22 am
Location: Eindhoven, The Netherlands
Contact:

Re: Reading In text file.

Post by Jasper » Wed Apr 07, 2010 6:26 am

Or a little more advanced, you can use LET on special variables:

Code: Select all

;;Defvar or defparameter *imalist* somewhere before
(let ((*imalist* (read-integers-from-file "/path/to/mydata.txt")))
  (function-depending-on-imalist)) ;Depends on the one as set
(function-depending-on-imalist) ;Doesn't depend on as set, outside that LET
It kindah sneaks in the special variable as argument where-ever it is needed.(So it is useful when you find yourself entering an argument unchanged all the time.) I am starting to like that feature as much as macros :).

Mercenary85
Posts: 10
Joined: Tue Apr 06, 2010 9:56 pm

Re: Reading In text file.

Post by Mercenary85 » Wed Apr 07, 2010 10:14 am

gugamilare wrote:To change the value of a variable, use setf. Like this:

Code: Select all

(defun read-integers-from-file (file)
  ;; reads file and returns a list with the integers inside it
  ...)

(defparameter *imalist* (list))

(setf *imalist* (read-integers-from-file "/path/to/mydata.txt"))
Oh ok that makes sense.
in the read-integers-from-file. what would I need to do to make sure it "stays" a global parameter
would something like THIS work

Code: Select all

(let ((in (open "data.txt" :if-does-not-exist nil)))
  (when in
    (loop for line = (read-line in nil)
         while line do (format t "~a~%" line))
    (close in)))
then have

Code: Select all

(defparameter *imalist* (list))

(setf *imalist* (read-integers-from-file "/path/to/mydata.txt")
like after that?
remember im new :)

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: Reading In text file.

Post by gugamilare » Wed Apr 07, 2010 10:52 am

Sorry, I didn't quite understand what you are trying to do. If you declare

Code: Select all

(defparameter *imalist* (list))
then *imalist* will still be a global variable no matter how many times you change its value using setf or let (like in Jasper's example). Or maybe what you want is not to change its value? In this case all you need to do is not to use setf and always use non-destructive functions when operating with your variable.

To know if a function is destructive, look at its documentation. For example, comparing delete and remove:

Code: Select all

cl-user> (documentation 'delete 'function)
"Return a sequence formed by destructively removing the specified ITEM from
  the given SEQUENCE."
cl-user> (documentation 'remove 'function)
"Return a copy of SEQUENCE with elements satisfying the test (default is
   EQL) with ITEM removed."
they do the same thing, but delete is destructive while remove is not.

Mercenary85
Posts: 10
Joined: Tue Apr 06, 2010 9:56 pm

Re: Reading In text file.

Post by Mercenary85 » Wed Apr 07, 2010 12:05 pm

Ok basically here is what Im trying to do.

I have a global parameter *mylist* that defines a list (like 1 3 5 6 3 1) etc...

Right now Im just using that as an example.

What I want to do is read in a text file (which consists of JUST integers) into the global parameter *mylist*. thats all I need to do.

So after the readin function, *mylist* will contain the numbers from the text file (if that makes sense)
the text file just has a bunch of integers in it

This code u listed above i think would work. except I dont know what goes in the "..." part. because this is my first time with lisp

Code: Select all

(defun read-integers-from-file (file)
  ;; reads file and returns a list with the integers inside it
  ...)

(defparameter *imalist* (list))

(setf *imalist* (read-integers-from-file "/path/to/mydata.txt"))

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: Reading In text file.

Post by gugamilare » Wed Apr 07, 2010 12:46 pm

Mercenary85 wrote:Ok basically here is what Im trying to do.

I have a global parameter *mylist* that defines a list (like 1 3 5 6 3 1) etc...

Right now Im just using that as an example.

What I want to do is read in a text file (which consists of JUST integers) into the global parameter *mylist*. thats all I need to do.

So after the readin function, *mylist* will contain the numbers from the text file (if that makes sense)
the text file just has a bunch of integers in it
Ok, so you are asking if *mylist* will "forget" its previous value and contain a list with only the numbers from the text file? Yes, that is what the code will do.
Mercenary85 wrote:This code u listed above i think would work. except I dont know what goes in the "..." part. because this is my first time with lisp
It seems you have a text file? You need the macro with-open-file and the function read. An example how it is supposed to do. If "data.txt" contains

Code: Select all

23 42 25
Then

Code: Select all

cl-user> (with-open-file (data "/home/gugamilare/data.txt")
           (format t "The first integer is ~A~%" (read data nil :eof))
           (format t "The second integer is ~A~%" (read data nil :eof))
           (format t "The third integer is ~A~%" (read data nil :eof))
           (format t "No more numbers in the file!~%The value returned by (read data nil :eof) is ~S~%"
                   (read data nil :eof)))
The first integer is 23
The second integer is 42
The third integer is 25
No more numbers in the file!
The value returned by (read data nil :eof) is :eof
nil
This is just an example, you will need to put this in a loop.

Jasper
Posts: 209
Joined: Fri Oct 10, 2008 8:22 am
Location: Eindhoven, The Netherlands
Contact:

Re: Reading In text file.

Post by Jasper » Wed Apr 07, 2010 12:55 pm

Mercenary85 wrote:except I dont know what goes in the "..." part. because this is my first time with lisp
In the vein of teaching to fish rather than giving fish: try use WITH-OPEN-FILE to open a file (could also just OPEN and CLOSE yourself) with READ, check they're numbers with NUMBERP then you could collect that into a list with LOOP like here, but with (prompt ..) replaced.

Mercenary85
Posts: 10
Joined: Tue Apr 06, 2010 9:56 pm

Re: Reading In text file.

Post by Mercenary85 » Wed Apr 07, 2010 1:26 pm

I understand the readin part. but I still dont see how that puts it into the global variable *mylist*?

Like if I define *mylist* as a parameter list thats blank.

then I read in the numbers from data.txt
and data.txt contains (5 6 7 1 5 12 6 7)

then after I readin. I want *mylist* (the global variable) to contain (5 6 7 1 5 12 6 7) and never lose those values (until i decide to change them)
would something like this work

Code: Select all

(defun read-setup (thefile)
(with-open-file (stream thefile)
    (loop for line = (read stream nil 'end)
          until (eq line 'end)           
          do (print (list (coerce line 'integer) ;want to make single list
                            )     
              )     
     )
)
)
then have this?

Code: Select all

(defparameter *imalist* (list))

(setf *imalist* (read-integers-from-file "/path/to/mydata.txt"))
would that store the integers into the global variable list *imalist*

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: Reading In text file.

Post by nuntius » Wed Apr 07, 2010 2:31 pm

Yes. (setf x y) stores y into the place currently known as x.

Post Reply