From: ·················@gmail.com
Subject: ASDF question - loading files
Date: 
Message-ID: <1141771289.090891.182540@i39g2000cwa.googlegroups.com>
Hello All,

I'm a bit of  a newbie to Lisp and I have been learning how to package
lisp code all nice and neat using asdf.  I have a project which
includes a large number of .lisp source files which are named
problem-1.lisp, problem-2.lisp, etc. up to over 100 files and growing.
Some files in the sequence are also not present.  So what I would like
to do is load these file programmatically and not have to list every
single file.   Check out my code below where I am generating the file
list using a loop macro.

----------- euler.asd ----------------
(require :util)

(defpackage :af.euler-system
  (:use :asdf :cl :af.util))
(in-package :afl.euler-system)

(defsystem euler
    :name "euler"
    :author "Anthony Fairchild <·················@gmail.com>"
    :version "1.0"
    :maintainer "Anthony Fairchild <·················@gmail.com>"
    :licence "BLAH"
    :description "Solutions for Project Euler at
http://www.mathschallenge.net"
    :long-description ""
    :depends-on (:util)
    :components (append '((:file "packages") ;; <--- compile error here
			  (:file "euler" :depends-on '("packages")))
			(loop for x from 1 to 300
			      when (file-exists? (format nil "problem-~d.lisp" x))
			      collect (list :file (format nil "problem-~d" x) :depends-on
'("packages")))))

;; This is what I had in :components before
#+nil((:FILE "packages")
		 (:FILE "euler" :DEPENDS-ON ("packages"))
		 (:FILE "problem-1" :DEPENDS-ON ("packages"))
		 (:FILE "problem-2" :DEPENDS-ON ("packages"))
		 (:FILE "problem-4" :DEPENDS-ON ("packages"))
		 (:FILE "problem-5" :DEPENDS-ON ("packages"))

                 ;;... cut for brevity

		 (:FILE "problem-112" :DEPENDS-ON ("packages")))
		 (:FILE "problem-113" :DEPENDS-ON ("packages")))
------------ end of euler.asd ------------

 When compiling this I get an error:

The value APPEND is not of type LIST.
   [Condition of type TYPE-ERROR]

Restarts:
  0: [ABORT] Abort SLIME compilation.
  1: [ABORT-REQUEST] Abort handling SLIME request.
  2: [TERMINATE-THREAD] Terminate this thread (#<THREAD "worker"
{AF13C99}>)

Backtrace:
  0: (ASDF::PARSE-COMPONENT-FORM #<SYSTEM "euler" {AE703E1}> APPEND)
  1: (ASDF::PARSE-COMPONENT-FORM NIL (:MODULE "euler" :PATHNAME
#P"/home/anthony/code/Lisp/source/euler/" :NAME "euler" :AUTHOR
"Anthony Fairchild <·················@gmail.com>" :VERSION "1.0" ...))
  2: ((SB-C::TOP-LEVEL-FORM (ASDF::PARSE-COMPONENT-FORM NIL (APPLY
#1="#<...>" . #1#))))
  3: (SB-FASL::LOAD-FASL-GROUP #<SB-SYS:FD-STREAM for "file
/home/anthony/code/Lisp/source/euler/euler.fasl" {B0F0D19}>)
...

It seems like the (append.... ) code is not getting evaluated before
the (defsystem) is.   Does anyone know of a way to fix this?  Any help
would be greatly appreciated

Anthony F.

From: Frank Buss
Subject: Re: ASDF question - loading files
Date: 
Message-ID: <174irmqbqzhl2.1nm7chydjxe8x.dlg@40tude.net>
·················@gmail.com wrote:

> (defsystem euler
>     :components (append '((:file "packages") ;; <--- compile error here
> 			  (:file "euler" :depends-on '("packages")))
> 			(loop for x from 1 to 300
> 			      when (file-exists? (format nil "problem-~d.lisp" x))
> 			      collect (list :file (format nil "problem-~d" x) :depends-on
> '("packages")))))

defsystem is a macro, so the "append" is not evaluated. See this for
example:

(defmacro foo (parameter)
  (let ((first-list (car parameter)))
    (format t "~a" first-list)))

CL-USER > (foo ((bar)))
(BAR)
NIL

CL-USER > (foo (append '((a)) '((b))))
APPEND
NIL

You can use the read-time evaluation macro to execute it at read-time:

CL-USER > (foo #.(append '((a)) '((b))))
(A)
NIL

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Frank Buss
Subject: Re: ASDF question - loading files
Date: 
Message-ID: <1epr7656nwsaz.1pc1md1kr98qy$.dlg@40tude.net>
·················@gmail.com wrote:

> 			      when (file-exists? (format nil "problem-~d.lisp" x))

BTW: "file-exists?" is not Common Lisp, maybe you mean "probe-file".

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: ·················@gmail.com
Subject: Re: ASDF question - loading files
Date: 
Message-ID: <1141784380.696150.86660@j52g2000cwj.googlegroups.com>
file-exists? is something I wrote using the examples from Practical
Common Lisp.  Like I said, I'm a newbie, I appreciate the comment.  I
will check out "probe-file".

Thanks,

Anthony F.
From: Pascal Bourguignon
Subject: Re: ASDF question - loading files
Date: 
Message-ID: <87d5gxbtek.fsf@thalassa.informatimago.com>
·················@gmail.com writes:

> Hello All,
>
> I'm a bit of  a newbie to Lisp and I have been learning how to package
> lisp code all nice and neat using asdf.  I have a project which
> includes a large number of .lisp source files which are named
> problem-1.lisp, problem-2.lisp, etc. up to over 100 files and growing.
> Some files in the sequence are also not present.  So what I would like
> to do is load these file programmatically and not have to list every
> single file.   Check out my code below where I am generating the file
> list using a loop macro.
>
> ----------- euler.asd ----------------
> (require :util)
>
> (defpackage :af.euler-system
>   (:use :asdf :cl :af.util))
> (in-package :afl.euler-system)
>
> (defsystem euler
>     :name "euler"
>     :author "Anthony Fairchild <·················@gmail.com>"
>     :version "1.0"
>     :maintainer "Anthony Fairchild <·················@gmail.com>"
>     :licence "BLAH"
>     :description "Solutions for Project Euler at
> http://www.mathschallenge.net"
>     :long-description ""
>     :depends-on (:util)
>     :components (append '((:file "packages") ;; <--- compile error here
> 			  (:file "euler" :depends-on '("packages")))
> 			(loop for x from 1 to 300
> 			      when (file-exists? (format nil "problem-~d.lisp" x))
> 			      collect (list :file (format nil "problem-~d" x) :depends-on
> '("packages")))))
> [...]
> It seems like the (append.... ) code is not getting evaluated before
> the (defsystem) is.   

Indeed. DEFSYSTEM is a macro and it determines itself what argument it
wants to evaluate, and what not.


> Does anyone know of a way to fix this?  Any help
> would be greatly appreciated

An easy way is to use the reader macro #. :

[24]> '(defsystem euler
     :name "euler"
     :author "Anthony Fairchild <·················@gmail.com"
     :version "1.0"
     :maintainer "Anthony Fairchild <·················@gmail.com"
     :licence "BLAH"
     :description "Solutions for Project Euler at http://www.mathschallenge.net"
     :long-description ""
     :depends-on (:util)
     :components #.(append '((:file "packages") ;; <--- compile error here
 			  (:file "euler" :depends-on '("packages")))
 			(loop for x from 1 to 300
 			      when (probe-file (format nil "problem-~d.lisp" x))
 			      collect (list :file (format nil "problem-~d" x) :depends-on
 '("packages")))))
(DEFSYSTEM EULER :NAME "euler" :AUTHOR "Anthony Fairchild <·················@gmail.com"
 :VERSION "1.0" :MAINTAINER "Anthony Fairchild <·················@gmail.com" :LICENCE
 "BLAH" :DESCRIPTION
 "Solutions for Project Euler at
 http://www.mathschallenge.net"
 :LONG-DESCRIPTION "" :DEPENDS-ON (:UTIL) :COMPONENTS
 ((:FILE "packages") (:FILE "euler" :DEPENDS-ON '("packages"))))

Note: the COMPONENTS are computed at READ time!



Another is to write a macro:

(defmacro computed-defsystem (name &rest others &key components &allow-other-keys)
  `(defsystem ,name
       ,@(loop for (k v) on others by (function cddr)
               unless (eq k :components) collect k
               unless (eq k :components) collect v)
       :components ,(eval components)))

[23]> (macroexpand-1 '(computed-defsystem euler
     :name "euler"
     :author "Anthony Fairchild <·················@gmail.com"
     :version "1.0"
     :maintainer "Anthony Fairchild <·················@gmail.com"
     :licence "BLAH"
     :description "Solutions for Project Euler at http://www.mathschallenge.net"
     :long-description ""
     :depends-on (:util)
     :components (append '((:file "packages") ;; <--- compile error here
 			  (:file "euler" :depends-on '("packages")))
 			(loop for x from 1 to 300
 			      when (probe-file (format nil "problem-~d.lisp" x))
 			      collect (list :file (format nil "problem-~d" x) :depends-on
 '("packages"))))))
(DEFSYSTEM EULER :NAME "euler" :AUTHOR "Anthony Fairchild <·················@gmail.com"
 :VERSION "1.0" :MAINTAINER "Anthony Fairchild <·················@gmail.com" :LICENCE
 "BLAH" :DESCRIPTION
 "Solutions for Project Euler at
 http://www.mathschallenge.net"
 :LONG-DESCRIPTION "" :DEPENDS-ON (:UTIL) :COMPONENTS
 ((:FILE "packages") (:FILE "euler" :DEPENDS-ON '("packages")))) ;
T

Note: the COMPONENTS are computed at MACRO-EXPANSION time!



One could also have COMPONENTS computed at RUN time:

(eval `(defsystem euler
     :name "euler"
     :author "Anthony Fairchild <·················@gmail.com"
     :version "1.0"
     :maintainer "Anthony Fairchild <·················@gmail.com"
     :licence "BLAH"
     :description "Solutions for Project Euler at http://www.mathschallenge.net"
     :long-description ""
     :depends-on (:util)
     :components ,(append '((:file "packages") ;; <--- compile error here
 			  (:file "euler" :depends-on '("packages")))
 			(loop for x from 1 to 300
 			      when (probe-file (format nil "problem-~d.lisp" x))
 			      collect (list :file (format nil "problem-~d" x) :depends-on
                        '("packages"))))))


But with the usual usage of defsystem, all these solutions should be
rather equivalent, since .asd files are not usually compiled for later
execution...

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

HEALTH WARNING: Care should be taken when lifting this product,
since its mass, and thus its weight, is dependent on its velocity
relative to the user.
From: ·················@gmail.com
Subject: Re: ASDF question - loading files
Date: 
Message-ID: <1141784814.215000.218360@i39g2000cwa.googlegroups.com>
Thank you for your quick responses.  I knew it would be something
simple like that.   I'm discovering more and more that I've just
scratched the surface of what lisp is capable of.  I'm having a lot of
fun!

Thanks again!

Anthony F.
From: ·················@gmail.com
Subject: Re: ASDF question - loading files
Date: 
Message-ID: <1141871431.784484.88320@j52g2000cwj.googlegroups.com>
Ok, I have another hopefully quick question.  The reader macro on
(append ...) worked great.  The only problem is the current working
directory is my user home directory "/home/anthony" instead of the ASDF
source directory where the files are located.  This requires me to use
the fully qualified path which is bad.   I did some digging around in
the ASDF documentation and there are ways to get at the files after the
package has been defined using FIND-SYSTEM and FIND-COMPONENT.  These
don't work inside the defsystem definition though.  Any ideas on how I
can settle these path issues?

Thanks!

AF

Here's my code:

---------------- euler.asd ---------------
(require :util)

(defpackage :af.euler-system
  (:use :asdf :cl :af.util))

(in-package :af.euler-system)

(defsystem euler
    :name "euler"
    :author "Anthony Fairchild <·················@gmail.com>"
    :version "1.0"
    :maintainer "Anthony Fairchild <·················@gmail.com>"
    :licence "BAH!"
    :description "Solutions for Project Euler at
http://www.mathschallenge.net"
    :long-description ""
    :depends-on (:util)
    :components #.(append '((:file "packages")
			    (:file "euler" :depends-on ("packages")))
			  (loop for x from 1 to 300
				when (probe-file (format nil ".clc/source/euler/problem-~d.lisp"
x)) ;;TODO: Hard coded path here.  BAD!
				collect (list :file (format nil "problem-~d" x) :depends-on
'("packages")))))
From: Petter Gustad
Subject: Re: ASDF question - loading files
Date: 
Message-ID: <87oe0gdpm7.fsf@filestore.home.gustad.com>
·················@gmail.com writes:


> 				when (probe-file (format nil ".clc/source/euler/problem-~d.lisp"
> x)) ;;TODO: Hard coded path here.  BAD!

I haven't followed this thread, but to me it appears that you're
looking for something like:

(probe-file 
 (make-pathname :directory (append (pathname-directory (user-homedir-pathname))                                  '(".clc" "source" "euler"))
                :name (format nil "problem-~d" x)
                :type "lisp"))

Petter
-- 
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?