Reputation: 13
I'm trying to get data from a file to an array char by char in lisp, but I'm very new to common lisp so I got lost on the way. Here's what I've tried so far and got lots of errors:
(defun gppinterpreter (filename)
(defvar *count* 0)
(setf my-array (make-array '(10)))
(with-open-file (stream filename)
(do ((char (read-char stream nil)
(read-char stream nil)))
((null char))
(setf (aref my-array *count*) char)
(set *count* (+ *count* 1))))
(print my-array)
)
Upvotes: 0
Views: 231
Reputation: 51501
That's not a bad start. Let's take a look at the errors one by one.
When you do a defvar
, it defines a global variable (to be more precise, with global lexical scope, dynamic extent). When you do that inside of a function body, this happens each time the function is run. This is not what you want. You want a variable that has only local lexical scope. Use let
for that:
(defun gppinterpreter (filename)
(let ((count 0)) ; <-
(setf my-array (make-array '(10)))
(with-open-file (stream filename)
(do ((char (read-char stream nil)
(read-char stream nil)))
((null char))
(setf (aref my-array count) char)
(set count (+ count 1))))
(print my-array)))
When you setf
a variable that doesn't exist, it gets created in the global lexical scope, but some of its behaviour is not specified. Don't do that. You want a local variable again. Use the let
:
(defun gppinterpreter (filename)
(let ((count 0)
(my-array (make-array '(10)))) ; <-
(with-open-file (stream filename)
(do ((char (read-char stream nil)
(read-char stream nil)))
((null char))
(setf (aref my-array count) char)
(set count (+ count 1))))
(print my-array)))
Set
is not setf
. I'll leave the specifics aside for now; set
is almost never what you want. You could use setf
there, but there is a convenient shorthand for incrementing a place, incf
:
(defun gppinterpreter (filename)
(let ((count 0)
(my-array (make-array '(10))))
(with-open-file (stream filename)
(do ((char (read-char stream nil)
(read-char stream nil)))
((null char))
(setf (aref my-array count) char)
(incf count))) ; <-
(print my-array)))
This version at least runs without errors and produces a char vector. You might replace the loop with a single call to read-sequence
, and instead of printing, you most likely want to just return the new vector:
(defun gppinterpreter (filename)
(let ((my-array (make-array '(10))))
(with-open-file (stream filename)
(read-sequence my-array stream)) ; <-
my-array)) ; <-
The next steps depend on what structure your file actually has. You might want to get a string instead of a general vector. You might want to read a line of text, with read-line
.
Upvotes: 1