Read next line when loading file in Common Lisp

203 views Asked by At

I have a file, test.lisp that is essentially this:

(load (compile-file "init.lisp"))
(my-funcA 2 3)
(my-funcB 4 5)
; bunch more lines like the last ones

Inside the init.lisp file i would like to be able to read the lines (my-funcA 2 3), (my-funcB 4 5), etc., and do stuff with it. Is this possible?

I've tried to use:

(let ((input (read)))
; do stuff here
)

inside the init.lisp file, but this just keeps waiting for input from the keybord, and doesn't read from the file that is loading. Any help would be much appreciated!

2

There are 2 answers

0
Barmar On

LOAD doesn't bind *STANDARD-INPUT* (or any other standard stream variable) to the file it's loading, so you need to do that yourself.

(defun load-with-stdin (filename) {
  (let ((eof '(:eof)))
    (with-open-file (*standard-input* filename)
      (loop for expr = (read *standard-input* nil eof)
            while (not (eq expr eof))
        do (eval expr)))))

(load-with-stdin "test.lisp")

However, this seems like a strange way to do things. Why not just define a function in init.lisp, and call it:

(load (compile-file "init.lisp")) ;; defines some-func
(some-func '(my-funcA 2 3))
(some-func '(my-funcB 4 5))
0
Throw Away Account On

Provided that init.lisp knows the name of the file loading it (perhaps because there's only one file that loads it and you can hard-code the name), you can read the lines by putting this in init.lisp:

(with-input-from-file (in "loader.lisp")
    (setf *load-form* (read in))  ;; *load-form* contains (load (compile-file "init.lisp"))
    (setf *my-func-a-form* (read in)) ;; (my-funcA 2 3)
    (setf *my-func-b-form* (read in))) ;; (my-funcB 4 5)

Since these forms are also part of the source code of "loader.lisp" (or whatever you're calling that file), they will be evaluated as soon as init.lisp finishes loading, regardless of what you do with them in init.lisp.

However, init.lisp can pull some awfully strange pranks, such as defining my-funca differently depending on what arguments it was called with:

(if (member 4 (cdr *my-func-a-form*))
    (defun my-funca (a)
        (format t "If you pass a literal 4 to me, then I only take one argument."))
    (defun my-funca (a b)
        (+ a (expt b a))))