Hi Michael,
This is how Jess behaved for all (read)s prior to version 4.1. The
problem here is that this -isn't- how CLIPS behaves for files, and
I've had a number of complaints from folks porting CLIPS file-handling
code. I'd like to maintain compatibility in this area; in general I've
tried to make Jess commands work as much like their CLIPS counterparts
as possible to make people's lives easier. Old versions of Jess
behaved correctly for the console, and incorrectly for files;
apparently the current version is misbehaving for certain combinations
of console calls, but the file handling is perfect.
In CLIPS, if you have the following file
A B
D E
then the following sequence of calls will return values as indicated:
(read) => A
(read) => B
(readline) => ""
(readline) => "D E"
on the other hand, from the console, if a (read) is issued and you
type
A B
the read will return 'A'. If a (readline) is then issued it will hang
until you type a newline.
I think I'm going to go with my earlier suggestion, that of internally
keeping track of two different kinds of routers: console-like ones and
other ones. It's the only way to get these two different behaviours.
I think Michael A. Fochtman wrote:
>
> Hi Ernest,
>
> FWIW, I was able to get correct behavior by simply changing the line in
> nextToken from:
>
> // ******************************
> // second and later characters of a multi-character token
> do
> {
> c = nextChar();
> if (Character.isSpace((char)c))
> {
> m_ios.reset();
> return finishToken(0, s);
> }
>
> to:
> // ******************************
> // second and later characters of a multi-character token
> do
> {
> c = nextChar(); if (Character.isSpace((char)c))
> {
> if(c!='\n') // don't replace whitespace if eol
> m_ios.reset();
> return finishToken(0, s);
> }
>
> As you can tell, this avoids putting back the first 'whitespace'
> character after a token if the char is a newline. This means that
> readline will not retrieve it. But, if the user enters just \r\n again,
> the readline will see it. This works because the token ends with a
> newline.
>
> I've been thinking it over, and this doesn't seem to be as bad a hack as
> I first thought. Whether reading from console or file, I can't think of
> when this newline would have been intended for read or readline to see
> it. If a blank line is intended for readline, then there would be two
> newlines in a row, one after the token, and another one on the next line
> of incoming text. If another read is performed after read, it would
> skip over the 'whitespace' anyway, so with this fix we just have one
> less whitespace character to skip over. By 'return finishToken(...)'
> we've already decided this token is ended, even though the next char in
> the input stream may not be whitespace (having not reset the \n char).
> I've pretty much convinced myself that this is one exception to putting
> back the first whitespace character found after a token. Have I
> convinced you?
>
> This fix doesn't depend on the streams source, whether console or file.
> Anyway, if you choose not to use this, I won't feel offended, or get
> indignant, but here it is 'for what its worth'.
>
> Mike
>
>
>
> -----Original Message-----
> From: Ernest Friedman-Hill [mailto:[EMAIL PROTECTED]]
>
>
> Hi Micahel,
>
> You're right, "Animals" is broken again.
>
> Lest everyone think I'm a complete moron, let me explain what's going
> on:
> 1) CLIPS' treatment of (read) and (readline) is -extremely-
> context-sensitive; 2) The buffering behaviour of Java's higher-level
> I/O streams change with each new release; 3) I personally rarely write
> systems that use (read).
>
> #2 is why Jess 4.1's biggest new feature is an entire new tokenization
> scheme that doesn't use DataInputStream or StreamTokenizer at
> all. Remember, that's what we're testing during this beta period!
>
> #1 is the biggest problem. CLIPS treats (read) and (readline)
> differently if the stream being read from is standard input as opposed
> to a file. At the console, (read) actually consumes an entire line of
> input (including the readline,) then keeps only the first token. In
> contrast, (read) from a file finds the next token, crossing line
> boundries only if needed. If the consumed token is the last token on a
> line, then the following newline is LEFT ON THE STREAM, so that a
> subsequent (readline) call returns an empty string.
>
> Now, in Java, "standard input" might be System.in, or a textfield in a
> GUI, or a network stream... so it's not clear how the implementation
> of read is supposed to know what kind of router it's talking to. I
> could special-case the 't' router, for example, I suppose; but this
> would not always help. For example, if I'm writing a GUI, and I
> install a new stream 'foo' connected to a GUI console, and I write
> rules to explicitly read from the 'foo' router, well, than this won't
> be enough.
>
> So here's an idea that strikes me as even uglier, but which I suppose
> would work: the 'addInputRouter' function gets another argument, a
> boolean named 'actAsConsole'. Routers added with this flag set to true
> get the console (read) behaviour; false give the file behaviour. Jess
> would internally take care of this for opened files and the standard
> streams, of course. I guess there'd need also to be a function
> getInputRouterBehavior().
>
> I guess that's not so bad. Thanks for giving me the chance to write
> this; it was therapeutic, and I might even get it straight this time! :)
>
>
> I think Michael A. Fochtman wrote:
> >
> > Hi all,
> >
> > Using Jess 41b2, I came across a problem with using read and readline.
> > I'm using NT4.0, VJ++ and MS SDK 2.01, just for the record.
> >
> > The problem can be seen in the 'animal.clp' demo, in the rule
> > 'replace-answer-node'. When the intrinsic function 'read' is called,
> it
> > eventually gets around to calling jess.Tokenizer.nextToken(). This
> > calls jess.Tokenizer.nextChar(). nextChar() correctly converts \r\n
> > pairs to \n. Since \n is considered whitespace, when nextChar()
> returns
> > that in the second loop of nextToken(), it puts the last char back by
> > calling m_ios.reset() and terminates. This seems okay.
> >
> > My problem is, when the rule then calls 'readline', the first
> character
> > read in is the \n put back by nextToken(). The function treats this
> as
> > the end of the line, and returns a string of zero length. (in the
> > animal.clp demo, when it asks for a question to differentiate the last
> > known animal with your new animal, it completes immediately with a
> zero
> > length question).
> >
> > Now it seems to me, that nextToken() is doing the right thing, by
> > restoring the first whitespace character after the token. And, it
> seems
> > reasonable for the readline method to allow entering just a newline
> for
> > a string of zero length. So, how do I get the animal.clp demo to
> > behave?? that is, get 'read' and 'readline' to work together??
> >
> > Or, maybe this isn't a problem with other compilers/javaVMs?? Anyone
> > have this problem on other platforms, java VM?
> >
> > TIA
> >
> > Mike Fochtman
> >
>
>
>
---------------------------------------------------------
Ernest Friedman-Hill
Distributed Systems Research Phone: (510) 294-2154
Sandia National Labs FAX: (510) 294-2234
Org. 8920, MS 9214 [EMAIL PROTECTED]
PO Box 969 http://herzberg.ca.sandia.gov
Livermore, CA 94550
---------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the
list. List problems? Notify [EMAIL PROTECTED]
---------------------------------------------------------------------