From: Will Duquette
Subject: Newbie in search of clues
Date: 
Message-ID: <3bbc729c.2105328@news.jpl.nasa.gov>
Howdy!

I've been experimenting with Common Lisp, mostly using Corman Lisp on
a Windows ME machine.  I've run across two problems, one involving
the (load) function, and one involving the CormanLisp IDE.

1. I've copied a few utility functions and macros from various sources
   into a file called "my.lisp", which I want to load from another
   file in the same directory.  But if I do

    (load "my.lisp")

   I get an error that the file doesn't exist....unless both files are
   in the CormanLisp directory.  How can I tell Lisp that I want
   to load a file that's in the same directory as the current file?
  (I've glanced at the write-up on "load" in Cltl2; it's tolerably
  opaque.)

2. In the CormanLisp IDE, standard input seems to have
   vanished.  What I mean is, whereas a couple of days ago
   typing (read-line) into the listener actually let me input
   something and then returned it, now (read-line) returns
   the empty-string immediately.  This has persisted across
   several restarts of CormanLisp.  Any ideas?

   Thanks!

Will Duquette

From: JP Massar
Subject: Re: Newbie in search of clues
Date: 
Message-ID: <3bbc8b60.85034661@news>
On Thu, 04 Oct 2001 14:36:53 GMT, ··················@jpl.nasa.gov
(Will Duquette) wrote:

 
>
>1. I've copied a few utility functions and macros from various sources
>   into a file called "my.lisp", which I want to load from another
>   file in the same directory.  But if I do
>
>    (load "my.lisp")
>
>   I get an error that the file doesn't exist....unless both files are
>   in the CormanLisp directory.  How can I tell Lisp that I want
>   to load a file that's in the same directory as the current file?
>  (I've glanced at the write-up on "load" in Cltl2; it's tolerably
>  opaque.)

Take a look at *load-pathname*.  This is bound to the pathname of the
file currently being loaded.  If you want to load file B in the same
directory as file A while loading file A, then you can construct
a full pathname for A by using the NAME and TYPE components of
(pathname A) and the DEVICE and DIRECTORY components of
*load-pathname*.  Then use LOAD on this new pathname.

Corman Lisp also has SET-CURRENT-DIRECTORY and CURRENT-DIRECTORY
functions.

So another way would be to do

(let ((old-current-directory (current-directory)))
  (unwind-protect
    (progn
      (set-current-directory *load-pathname*)
      (load "my.lisp")
      )
    (set-current-directory old-current-directory)
    )


>
>2. In the CormanLisp IDE, standard input seems to have
>   vanished.  What I mean is, whereas a couple of days ago
>   typing (read-line) into the listener actually let me input
>   something and then returned it, now (read-line) returns
>   the empty-string immediately.  This has persisted across
>   several restarts of CormanLisp.  Any ideas?
>
 
I get the same behavior in the IDE (returns "" immediately).
Don't know how you would have gotten a different behavior previously.
From: JP Massar
Subject: Re: Newbie in search of clues, retract
Date: 
Message-ID: <3bbc9235.86783221@news>
 
This doesn't work.  SET-CURRENT-DIRECTORY doesn't change
the default directory for LOAD, which uses
*default-pathname-defaults*.

SET-CURRENT-DIRECTORY just makes a Windows OS call to chdir.

So the way to do it is

(load (merge-pathnames "my.lisp" *load-pathname*))

which implements my first suggestion.

>
>So another way would be to do
>
>(let ((old-current-directory (current-directory)))
>  (unwind-protect
>    (progn
>      (set-current-directory *load-pathname*)
>      (load "my.lisp")
>      )
>    (set-current-directory old-current-directory)
>    )
>
 
From: Will Duquette
Subject: Re: Newbie in search of clues, retract
Date: 
Message-ID: <3bbceae8.32901484@news.jpl.nasa.gov>
On Thu, 04 Oct 2001 16:51:39 GMT, ······@alum.mit.edu (JP Massar)
wrote:

>>
>(load (merge-pathnames "my.lisp" *load-pathname*))
>
>which implements my first suggestion.

Excellent!  I'm still hazy on all of the CL pathname stuff, and though
I'd seen merge-pathnames in cltl2 it wasn't at all clear to me how to
use it.  Thanks!
From: Roger Corman
Subject: Re: Newbie in search of clues
Date: 
Message-ID: <3bbd511b.1300377574@news.callatg.com>
On Thu, 04 Oct 2001 16:34:26 GMT, ······@alum.mit.edu (JP Massar) wrote:

>On Thu, 04 Oct 2001 14:36:53 GMT, ··················@jpl.nasa.gov
>(Will Duquette) wrote:
>>2. In the CormanLisp IDE, standard input seems to have
>>   vanished.  What I mean is, whereas a couple of days ago
>>   typing (read-line) into the listener actually let me input
>>   something and then returned it, now (read-line) returns
>>   the empty-string immediately.  This has persisted across
>>   several restarts of CormanLisp.  Any ideas?
>>
> 
>I get the same behavior in the IDE (returns "" immediately).
>Don't know how you would have gotten a different behavior previously.

Take heart, standard input has not vanished!

In the Corman Lisp IDE, when you execute an expression, a newline character
gets appended on the end of the characters that are passed to standard input.
The expression gets read, then evaluated. When READ-LINE executes it
reads text up until it encounters a newline, which is probably the first
character following the expression. Therefore you end up with just an empty
line.

I can think of three simple things that work:

(progn (read-line)(read-line))

(progn (read-char)(read-line))

(progn (clear-input)(read-line))

These all work and do what you want when typed at the command line.
The same comments also apply when using the console application.

I prefer the latter of the three methods (using CLEAR-INPUT) because
I think it is the most clear (no pun intended). All three cases use the
first expression to get rid of the newline character.

However, when you are writing an application, or a function which does various
I/O and uses READ-LINE, this isn't normally a problem. It is only a by-product
of the read-eval-print loop processing.

Roger
From: Will Duquette
Subject: Re: Newbie in search of clues
Date: 
Message-ID: <3bbdc10e.87724640@news.jpl.nasa.gov>
On Fri, 05 Oct 2001 06:29:13 GMT, ·····@corman.net (Roger Corman)
wrote:

>Take heart, standard input has not vanished!
>
>In the Corman Lisp IDE, when you execute an expression, a newline character
>gets appended on the end of the characters that are passed to standard input.
>The expression gets read, then evaluated. When READ-LINE executes it
>reads text up until it encounters a newline, which is probably the first
>character following the expression. Therefore you end up with just an empty
>line.
>
>I can think of three simple things that work:
>
>(progn (read-line)(read-line))
>
>(progn (read-char)(read-line))
>
>(progn (clear-input)(read-line))

<snip>

Well, how's that for customer service!  My thanks.

Will Duquette
From: Kent M Pitman
Subject: Re: Newbie in search of clues
Date: 
Message-ID: <sfwy9mr73dz.fsf@world.std.com>
··················@jpl.nasa.gov (Will Duquette) writes:

> I've been experimenting with Common Lisp, mostly using Corman Lisp on
> a Windows ME machine.  I've run across two problems, one involving
> the (load) function, and one involving the CormanLisp IDE.
 
I can't speak for Corman CL, but the problems you cite are common to most
implementations.

> 1. I've copied a few utility functions and macros from various sources
>    into a file called "my.lisp", which I want to load from another
>    file in the same directory.  But if I do
> 
>     (load "my.lisp")
> 
>    I get an error that the file doesn't exist....unless both files are
>    in the CormanLisp directory.  How can I tell Lisp that I want
>    to load a file that's in the same directory as the current file?
>   (I've glanced at the write-up on "load" in Cltl2; it's tolerably
>   opaque.)

It's up to the vendor to arrange what the "foothold" directory is, but
generally for most lisps it's the directory you start Lisp from if you
do it from the command line.  In Windows, most "shortcut" aliases have,
in the alias document's properties (which you get to by right-clicking
the alias, and selecting "Properties"), the ability to set a working directory
for Lisp to start in (it's in the Shortcut tab, not the General tab, so
won't appear at first when you open Properties).  

On something  like WindowsNT or Windows 2000 with
a "real" concept of users each with their own home dirs, it works to put
%HOMEDRIVE%%HOMEPATH% to get the homedir for the user.  Windows 95/98/ME
have no real concept of homedir, so you probably have to just set the
value to D:/Users/William or whatever dir you want that alias to start in.

> 2. In the CormanLisp IDE, standard input seems to have
>    vanished.  What I mean is, whereas a couple of days ago
>    typing (read-line) into the listener actually let me input
>    something and then returned it, now (read-line) returns
>    the empty-string immediately.  This has persisted across
>    several restarts of CormanLisp.  Any ideas?

Often an implementation will read from the line you activated from.
That is, you have to write 
 (read-line)foo<ENTER>
if you want "foo" to come back since it will start taking data immediately
after the open paren.  In a "real" application, of course, the invocation
line won't be an issue.  In some implementations, if you do output 
intervening, you will get around this. e.g.,
 (progn (princ "Foo: ") (read-line))
 Foo: foo<ENTER>

It may be that what it was doing before and what it's doing now are the same
but that you're confusing yourself by the behavior of the very first line.
If you had read multiple lines instead of one, it might have been easier
to see what's going on.  Try
 (list (read-line) (read-line))foo
 bar
 baz

and see if ("foo" "bar") or ("bar" "baz") gets returned or if something else
happens.

If this turns out to be your problem, and if it troubles you,
you might want to write yourself an augmented input reader like
the following which is insensitive to blank lines:

 (defun read-non-empty-line-or-abort (&optional (stream *standard-input*))
   (loop (let ((line (read-line stream nil nil)))
           (cond ((not line) (return nil)) ;end of file
                 ((equal line "")) ;ignore blank lines, loop and try another
                 ((equalp line ·@abort") ;Let user type ·@abort" to abort
                  (abort))
                 (t (return line))))))

(A still more elaborate version of same might take a prompt and might re-prompt
if you typed an blank line.)
From: Will Duquette
Subject: Re: Newbie in search of clues
Date: 
Message-ID: <3bbceb9a.33079968@news.jpl.nasa.gov>
On Thu, 4 Oct 2001 16:53:44 GMT, Kent M Pitman <······@world.std.com>
wrote:

>··················@jpl.nasa.gov (Will Duquette) writes:
>It's up to the vendor to arrange what the "foothold" directory is, but
>generally for most lisps it's the directory you start Lisp from if you
>do it from the command line.  In Windows, most "shortcut" aliases have,
>in the alias document's properties (which you get to by right-clicking
>the alias, and selecting "Properties"), the ability to set a working directory
>for Lisp to start in (it's in the Shortcut tab, not the General tab, so
>won't appear at first when you open Properties).  

This is what I get for goofing around with this at home.  I do so
little programming in the Windows environment these days that
I forgot entirely about this...which is, really, exactly what I need
at the moment.  I'm not looking to deliver an application, I
just want to make things more convenient while I'm learning.

>Often an implementation will read from the line you activated from.
>That is, you have to write ...
<snip>

Thanks for the detailed and cogent response!

Will Duquette

> (read-line)foo<ENTER>
>if you want "foo" to come back since it will start taking data immediately
>after the open paren.  In a "real" application, of course, the invocation
>line won't be an issue.  In some implementations, if you do output 
>intervening, you will get around this. e.g.,
> (progn (princ "Foo: ") (read-line))
> Foo: foo<ENTER>
>
>It may be that what it was doing before and what it's doing now are the same
>but that you're confusing yourself by the behavior of the very first line.
>If you had read multiple lines instead of one, it might have been easier
>to see what's going on.  Try
> (list (read-line) (read-line))foo
> bar
> baz
>
>and see if ("foo" "bar") or ("bar" "baz") gets returned or if something else
>happens.
>
>If this turns out to be your problem, and if it troubles you,
>you might want to write yourself an augmented input reader like
>the following which is insensitive to blank lines:
>
> (defun read-non-empty-line-or-abort (&optional (stream *standard-input*))
>   (loop (let ((line (read-line stream nil nil)))
>           (cond ((not line) (return nil)) ;end of file
>                 ((equal line "")) ;ignore blank lines, loop and try another
>                 ((equalp line ·@abort") ;Let user type ·@abort" to abort
>                  (abort))
>                 (t (return line))))))
>
>(A still more elaborate version of same might take a prompt and might re-prompt
>if you typed an blank line.)