From: Fred Nicolier
Subject: what's wrong with my streams ?
Date: 
Message-ID: <slrndigd57.2mso.f.nicolier@station5.iut-troyes.univ-reims.fr>
Hello,

I actually try to interface (roughly) octave (an interpreted command
line numerical language) with lisp. In order make some tests i wrote
the following codes :

(defvar p)

(defun start ()
  (progn 
    (setf p (ext:run-program "octave" '("-qi")
                             :wait nil
                             :input :stream
                             :output :stream
                             :error :stream))
    (in "PS1=\"\";")))

(defun stop ()
  (process-close p))

(defun out ()
  (let ((out (process-output p)))
    (concatenate 'string (loop for c = (read-char-no-hang out)
                               while c
                               collect c))))
  
(defun in (str)
  (let ((in (process-input p)))
    (progn
      (write-line str in)
      (force-output in))))

All is ok in slime repl, as in :

> (start)  
> (in "a=1;disp(a)")
> (out)                                                                                                             
"octave-2.1.57:1> 1"

But the following function do not produce any result :

(defun test ()
    (let ((o))
      (start)
      (in "a=1;disp(a)")
      (setf o (out))
      (stop)
      o))

My lisp is cmucl. I think i don't understand something with streams but why ?

Fred

From: Harold
Subject: Re: what's wrong with my streams ?
Date: 
Message-ID: <1126712371.119580.59850@f14g2000cwb.googlegroups.com>
Your OUT function does not wait for output if it is not available right
away. I think that there is not enough of a delay between your calls to
IN and OUT for Octave to respond.

I tried putting a delay in, and that worked for me:

(defun test ()
    (let ((o))
      (start)
      (in "a=1;disp(a)")
      (sleep 1)
      (setf o (out))
      (stop)
      o))

Of course, you can't predict how long it will take for Octave, or some
other child process, to respond.
From: Thomas Bakketun
Subject: Re: what's wrong with my streams ?
Date: 
Message-ID: <1446915.mIc9oUIxgJ@kokusbolle.bakketun.net>
* Harold:

> Of course, you can't predict how long it will take for Octave, or some
> other child process, to respond.

But Octave will display a prompt when done.  Just set the prompt to
something that never will occur elsewere.  The bell character might be a
safe choice:

(defvar *octave-process*)

(defun start ()
  (setf *octave-process* (ext:run-program "octave" '("-qi")
      :wait nil
      :input :stream
      :output :stream
      :error :stream))
  (in "PS1=\"\\a\";")
  (out))

(defun out ()
  (let ((out (process-output *octave-process*)))
    (concatenate 'string (loop for c = (read-char out)
                               until (char= #\Bell c)
                               collect c))))
From: Harald Hanche-Olsen
Subject: Re: what's wrong with my streams ?
Date: 
Message-ID: <pco8xxzpj2v.fsf@shuttle.math.ntnu.no>
This is not a reply to your question, but I thought I would point out
a style problem in your code.

+ Fred Nicolier <··········@gmail.com>:

| (defun start ()
|   (progn 
|     (setf p (ext:run-program "octave" '("-qi")
|                              :wait nil
|                              :input :stream
|                              :output :stream
|                              :error :stream))
|     (in "PS1=\"\";")))
| 
| [...]
| 
| (defun in (str)
|   (let ((in (process-input p)))
|     (progn
|       (write-line str in)
|       (force-output in))))

The body of a function or a LET is already an implicit progn, so
wrapping them in an explicit PROGN will just confuse readers of your
program.  These PROGNs are just noise.  Get rid of them.

Perhaps we should institute a "Useless use of PROGN award" on c.l.l.?

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Fred Nicolier
Subject: Re: what's wrong with my streams ?
Date: 
Message-ID: <slrndilhtu.3035.f.nicolier@station5.iut-troyes.univ-reims.fr>
Ok for the progn.

For the rest of the code, i've replaced the out function with :

(defun out ()
  (let ((out  (process-output *octave-process*)))
    (read-line out)))

and it work nice.

I wonder why i was using read-char-no-hang.

Thanks.

Fred
From: Harald Hanche-Olsen
Subject: Re: what's wrong with my streams ?
Date: 
Message-ID: <pcor7bpm72f.fsf@shuttle.math.ntnu.no>
+ Fred Nicolier <··········@gmail.com>:

| For the rest of the code, i've replaced the out function with :
| 
| (defun out ()
|   (let ((out  (process-output *octave-process*)))
|     (read-line out)))

Which can be written shorter as

(defun out ()
  (read-line (process-output *octave-process*)))

with no penalty in readability.  Quite the contrary, I think.

Oh, I do the same thing all the time myself:  I compute something and
assign it to a variable, only to discover later that I am using the
value only once, so I might as well compute it in the place where it's
used.  But sometimes it's good to leave the extra let binding in, like
when a lot of stuff is computed and assigned to variables, some of
which because the values are used in several places.  Then it may
occasionally be clearer to treat all the values the same.

| I wonder why i was using read-char-no-hang.

Ha.  If I always knew why I did something which turned out later not
to be so smart, I would know a lot about myself.  And none of it very
flattering, I'm afraid.  8-)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow