From: sj
Subject: Load path question
Date: 
Message-ID: <UQbvi.44977$Um6.2396@newssvr12.news.prodigy.net>
Just getting into Common Lisp and was wondering if there is a way to set the
search path for load?  Specifically I want to be able to search multible
directories with a single call to load. 

Thanks in Advance

From: Rainer Joswig
Subject: Re: Load path question
Date: 
Message-ID: <joswig-241BA6.13081711082007@news-europe.giganews.com>
In article <····················@newssvr12.news.prodigy.net>,
 sj <·······@swbell.net> wrote:

> Just getting into Common Lisp and was wondering if there is a way to set the
> search path for load?  Specifically I want to be able to search multible
> directories with a single call to load. 
> 
> Thanks in Advance

LOAD takes a pathname not a 'search path'.

Your implementation might support something like that
together with REQUIRE or a system facility.

Other than that write it yourself. In the great tradition of untested
and unfinished code on c.l.l ;-) :

(defparameter *directories-to-search* (list ... ))

(defun my-load-using-directories (name &optional (dirs *directories-to-search*))
   (loop for dir in dirs
         for file = (merge-pathname name dir)
         for file-exists = (probe-file file)
         when file-exists do (load file)
         unless file-exists))

-- 
http://lispm.dyndns.org
From: Rob Warnock
Subject: Re: Load path question
Date: 
Message-ID: <K8udnV0ycJOG_SPbnZ2dnUVZ_gmdnZ2d@speakeasy.net>
Rainer Joswig  <······@lisp.de> wrote:
+---------------
| Other than that write it yourself. In the great tradition of untested
| and unfinished code on c.l.l ;-) :
| (defparameter *directories-to-search* (list ... ))
| (defun my-load-using-directories (name
|                                   &optional (dirs *directories-to-search*))
|   (loop for dir in dirs
|         for file = (merge-pathname name dir)
|         for file-exists = (probe-file file)
|         when file-exists do (load file)
|         unless file-exists))
+--------------

Minor correctness & style quibbles[1]:

0. MERGE-PATHNAMES, not MERGE-PATHNAME.

1. The final UNLESS clause is missing a "selectable-clause" after
    the test form. You probably meant to use UNTIL instead.

2. UNTIL would be correct, but that style of LOOP termination might
   be a bit obscure. I would suggest this instead, which also has
   the advantage of returning a potentially-useful value from LOAD:

   (defun my-load-using-directories (name
				     &optional (dirs *directories-to-search*))
     (loop for dir in dirs
           for file = (merge-pathnames name dir)
           for file-exists = (probe-file file)
           when file-exists
	     do (return (load file))))

And that version, now *very* lightly tested, does seem to work:

    > *directories-to-search*

    ("home:" "home:tmp/" "home:src/try/")
    > (my-load-using-directories "foo")

    ; Loading #P"/u/rpw3/tmp/foo".
    hello, world!
    T
    > 

-Rob

[1] In the great tradition of quibbling about untested and
    unfinished code on c.l.lisp.  ;-)

[2] And in the equally great tradition of generalizing tiny CL examples
    to their maximal -- dare I say, overblown?!? -- generality, I offer
    this additional version:   ;-}   ;-}

    > (defun my-load-using-directories (name
					&rest rest
					&key (directory-list
					      *directories-to-search*) 
					&allow-other-keys)
	 (loop for dir in directory-list
	       for file = (merge-pathnames name dir)
	       for file-exists = (probe-file file)
	       when file-exists
		 do (return (apply #'load file :allow-other-keys t rest))))

    MY-LOAD-USING-DIRECTORIES
    > (my-load-using-directories "foo" :verbose nil :print t)

    hello, world!
    ; NIL
    ; (EXPT 2 100)
    ; =
    ; 1267650600228229401496703205376
    T
    > 

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Steven E. Harris
Subject: Re: Load path question
Date: 
Message-ID: <83vebk20qs.fsf@torus.sehlabs.com>
····@rpw3.org (Rob Warnock) writes:

> 	       for file-exists = (probe-file file)
> 	       when file-exists
> 		 do (return (apply #'load file :allow-other-keys t rest))))

And why not get rid of "file-exists"? Just write

  when (probe-file file)

unless you think the meaning of probe-file is lost in the contraction.

-- 
Steven E. Harris
From: Rob Warnock
Subject: Re: Load path question
Date: 
Message-ID: <cPmdnYcJd4CgIiLbnZ2dnUVZ_ufinZ2d@speakeasy.net>
Steven E. Harris <···@panix.com> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| > 	       for file-exists = (probe-file file)
| > 	       when file-exists
| > 		 do (return (apply #'load file :allow-other-keys t rest))))
| 
| And why not get rid of "file-exists"? Just write
|   when (probe-file file)
| unless you think the meaning of probe-file is lost in the contraction.
+---------------

Nope, just didn't think of it. [It wasn't "wrong", like
some of my other corrections, so I just left it alone.]


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: sj
Subject: Re: Load path question
Date: 
Message-ID: <MOcwi.33225$2v1.25757@newssvr14.news.prodigy.net>
Thanks for all the replies.  I ended up taking a slightly different approach
factoring out load from the directory search code. I also added a list of
possible file extensions so the algorithm will match "foo" to both "foo"
and "foo.lisp" or whatever extension is desired. 


(defvar *load-directory-list* '())

(defun add-load-directory (dir)
  (pushnew dir *load-directory-list* :test #'equal))


(add-load-directory "home/sj/src/lisp")
(add-load-directory "home/sj/src/lisp/sjutil")
(add-load-directory "home/sj/src/lisp/sjutil/foo")



(defvar *load-type-list* '())

(defun add-load-type (ext)
  (pushnew ext *load-type-list* :test #'equal))


(add-load-type nil)
(add-load-type "lisp")


      
;; Return pathname of first matching file on search directory 
;; list. If no match return nil. 
;;
(defun which-file (name &key (dirs *load-directory-list*)
                   (extension-list *load-type-list*))
  (loop for dir in (reverse dirs) do
        (loop for e in (reverse extension-list) 
              for pathname = (make-pathname :directory dir
                                            :name name
                                            :type e)
              for file-exist = (probe-file pathname)
              when file-exist do
                    (return-from which-file pathname)))
  nil)


-- Steven Jones

 
From: Rob Warnock
Subject: Re: Load path question
Date: 
Message-ID: <p7-dnTNz5sDA_FzbnZ2dnUVZ_tuonZ2d@speakeasy.net>
sj <·······@swbell.net> wrote:
+---------------
| Thanks for all the replies.  I ended up taking a slightly different
| approach factoring out load from the directory search code. I also
| added a list of possible file extensions so the algorithm will match
| "foo" to both "foo" and "foo.lisp" or whatever extension is desired. 
+---------------

I think you need to make it be a tiny bit smarter than this.
For example, on an x86 platform when you ask CMUCL to (LOAD "foo"),
it first tries "foo", then "foo.x86f" [its extension for hard-
ompiled code on x86], then "foo.lbytef" [its extension for
byte-compiled code on LittleEndian machines], then "foo.fasl"
[the generic extension for compiled code], then finally "foo.lisp",
"foo.l", "foo.cl", and "foo.lsp", in that order.

Plus, by default, if you have both a compiled version [e.g.,
"foo.x86f"] and a source version [e.g., "foo.lisp"] and the
latter is newer than the former, it will warn you [but load
the older binary version anyway]:

    cmu> (load "foo")
    Warning:  Loading object file /u/rpw3/foo.x86f,
    which is older than the presumed source:
      /u/rpw3/foo.lisp.

    ; Loading #P"/u/rpw3/foo.x86f".
    Hi! My name is #P"/u/rpw3/foo.x86f".
    T
    cmu> 

You can override this and get very useful behavior by specifying
the non-standard :IF-SOURCE-NEWER keyword with the :COMPILE option,
like this:

    cmu> (load "foo" :if-source-newer :compile)

    ; Python version 1.1, VM version Intel x86 on 14 AUG 07 12:47:55 am.
    ; Compiling: /u/rpw3/foo.lisp 14 AUG 07 12:47:51 am

    ; Byte Compiling Top-Level Form: 

    ; foo.x86f written.
    ; Compilation finished in 0:00:00.

    ; Loading #P"/u/rpw3/foo.x86f".
    Hi! My name is #P"/u/rpw3/foo.x86f".
    T
    cmu>

Do it again, and it doesn't recompile, of course:

    cmu> (load "foo" :if-source-newer :compile)

    ; Loading #P"/u/rpw3/foo.x86f".
    Hi! My name is #P"/u/rpw3/foo.x86f".
    T
    cmu> 

Whichever implementation of CL you're using will likely have
similar behavior regarding defaulting file types and possibly
similar extensions builtin, so you want to make sure your
WHICH-FILE is at *least* as smart as your implementation's
builtins w.r.t. source vs. binary, and also modification dates.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Rainer Joswig
Subject: Re: Load path question
Date: 
Message-ID: <joswig-A222F7.14021714082007@news-europe.giganews.com>
In article <·····················@newssvr14.news.prodigy.net>,
 sj <·······@swbell.net> wrote:

> Thanks for all the replies.  I ended up taking a slightly different approach
> factoring out load from the directory search code. I also added a list of
> possible file extensions so the algorithm will match "foo" to both "foo"
> and "foo.lisp" or whatever extension is desired. 
> 
> 
> (defvar *load-directory-list* '())
> 
> (defun add-load-directory (dir)
>   (pushnew dir *load-directory-list* :test #'equal))
> 
> 
> (add-load-directory "home/sj/src/lisp")
> (add-load-directory "home/sj/src/lisp/sjutil")
> (add-load-directory "home/sj/src/lisp/sjutil/foo")
> 
> 
> 
> (defvar *load-type-list* '())
> 
> (defun add-load-type (ext)
>   (pushnew ext *load-type-list* :test #'equal))
> 
> 
> (add-load-type nil)
> (add-load-type "lisp")
> 
> 
>       
> ;; Return pathname of first matching file on search directory 
> ;; list. If no match return nil. 
> ;;
> (defun which-file (name &key (dirs *load-directory-list*)
>                    (extension-list *load-type-list*))
>   (loop for dir in (reverse dirs) do
>         (loop for e in (reverse extension-list) 
>               for pathname = (make-pathname :directory dir
>                                             :name name
>                                             :type e)
>               for file-exist = (probe-file pathname)
>               when file-exist do
>                     (return-from which-file pathname)))
>   nil)
> 
> 
> -- Steven Jones
> 
>  

Just a minor note. Common Lisp supports comments
in functions. Any self-respecting IDE will use those.

LispWorks: m-c-sh-a on a symbol shows the function documentation.
Zmacs: c-sh-d.
SLIME seems to have no command?

SLIME and LispWorks highlights them as strings, which is definitely
better than nothing - it should highlight them
as comments, though.

(defun which-file (name &key (dirs *load-directory-list*)
                        (extension-list *load-type-list*))
  "Return pathname of first matching file on search directory 
list. If no match return nil."
  ;; gdfgdf
  (loop for dir in (reverse dirs) do
        (loop for e in (reverse extension-list) 
              for pathname = (make-pathname :directory dir
                                            :name name
                                            :type e)
              for file-exist = (probe-file pathname)
              for foo = "dfkghdfkghdkf"
              when file-exist do
              (return-from which-file pathname))))
From: Rainer Joswig
Subject: Re: Load path question
Date: 
Message-ID: <joswig-C92DBA.13585312082007@news-europe.giganews.com>
In article <································@speakeasy.net>,
 ····@rpw3.org (Rob Warnock) wrote:

> Rainer Joswig  <······@lisp.de> wrote:
> +---------------
> | Other than that write it yourself. In the great tradition of untested
> | and unfinished code on c.l.l ;-) :
> | (defparameter *directories-to-search* (list ... ))
> | (defun my-load-using-directories (name
> |                                   &optional (dirs *directories-to-search*))
> |   (loop for dir in dirs
> |         for file = (merge-pathname name dir)
> |         for file-exists = (probe-file file)
> |         when file-exists do (load file)
> |         unless file-exists))
> +--------------
> 
> Minor correctness & style quibbles[1]:
> 
> 0. MERGE-PATHNAMES, not MERGE-PATHNAME.
> 
> 1. The final UNLESS clause is missing a "selectable-clause" after
>     the test form. You probably meant to use UNTIL instead.
> 
> 2. UNTIL would be correct, but that style of LOOP termination might
>    be a bit obscure. I would suggest this instead, which also has
>    the advantage of returning a potentially-useful value from LOAD:
> 
>    (defun my-load-using-directories (name
> 				     &optional (dirs *directories-to-search*))
>      (loop for dir in dirs
>            for file = (merge-pathnames name dir)
>            for file-exists = (probe-file file)
>            when file-exists
> 	     do (return (load file))))
> 
> And that version, now *very* lightly tested, does seem to work:
> 
>     > *directories-to-search*
> 
>     ("home:" "home:tmp/" "home:src/try/")
>     > (my-load-using-directories "foo")
> 
>     ; Loading #P"/u/rpw3/tmp/foo".
>     hello, world!
>     T
>     > 
> 
> -Rob
> 
> [1] In the great tradition of quibbling about untested and
>     unfinished code on c.l.lisp.  ;-)

Thanks, Rob!

> 
> [2] And in the equally great tradition of generalizing tiny CL examples
>     to their maximal -- dare I say, overblown?!? -- generality, I offer
>     this additional version:   ;-}   ;-}
> 
>     > (defun my-load-using-directories (name
> 					&rest rest
> 					&key (directory-list
> 					      *directories-to-search*) 
> 					&allow-other-keys)
> 	 (loop for dir in directory-list
> 	       for file = (merge-pathnames name dir)
> 	       for file-exists = (probe-file file)
> 	       when file-exists
> 		 do (return (apply #'load file :allow-other-keys t rest))))
> 
>     MY-LOAD-USING-DIRECTORIES
>     > (my-load-using-directories "foo" :verbose nil :print t)
> 
>     hello, world!
>     ; NIL
>     ; (EXPT 2 100)
>     ; =
>     ; 1267650600228229401496703205376
>     T
>     > 
> 
> -----
> Rob Warnock			<····@rpw3.org>
> 627 26th Avenue			<URL:http://rpw3.org/>
> San Mateo, CA 94403		(650)572-2607

-- 
http://lispm.dyndns.org