On 20 Sep 2012, at 13:48, David Matthews wrote:
> On 20/09/2012 08:20, Lars-Henrik Eriksson wrote:
>> 19 sep 2012 kl. 18.00 skrev David Matthews:
>>
>> Also the same ML code *will* behave differently when run
>> interactively or stand-alone using Poly/ML:
>>
>> Poly/ML 5.5.0 Release
>>> fun f() = (print "Say something: "; TextIO.inputLine TextIO.stdIn;
>>> print "Thank you.\n");
>> val f = fn: unit -> unit
>>> PolyML.export("test",f);
>> val it = (): unit
>>> f();Hello
>> Say something: Thank you. val it = (): unit
>>
>> unix> ./test Say something: Hello Thank you.
>>
>> I believe that the stand-alone behavior is the reasonable one -- it
>> also agrees with SML/NJ and Moscow ML.
>
> If you remember that the read-eval-print loop uses TextIO.input1 rather than
> TextIO.inputLine it all makes sense. At the end of compiling the next
> character to be read from stdIn is the character immediately after the
> closing semicolon. That may or may not be a newline character depending on
> what the rest of the input was. If the code that has just been compiled
> wants to read from the stream this is where it starts. The next time round
> the loop the compiler starts after anything that has been removed. When
> running as a stand-alone executable the behaviour is exactly the same; it's
> just that the compiler has not been run so the function starts at the
> beginning of the stream.
>
>> Does this cause problems? Yes, for me it does. We use ML in the
>> introductory programming course for CS majors and it causes
>> unnecessary complications for the students.
>
> I am not completely wedded to the present way of doing things but I feel
> there has to be a stronger rationale for changing it. I would be interested
> to know if anyone else has feelings one way or the other.
I have fairly strong feelings that it is not worth worrying about. Personally,
I find the Poly/ML behaviour more to my liking than the SML/NJ behaviour
because beginning execution immediately after reading the semicolon feels more
intuitive. Programmers and language implementors are all doomed if the rest of
the line containing the i/o command is not syntactically complete, as in:
print "Type something, please: "; val x = TextIO.inputLine TextIO.stdIn; print (
"thank you!");
(Poly/ML and SML/NJ both bind something to x and then report a syntax error,
but the value of x and the syntax errors are different: in Poly/ML, the left
bracket has been consumed into x and the right bracket is unmatched, but vice
versa for SML/NJ.)
In any case, isn't this an issue for the implementation of the basis library
rather than the compiler proper? I don't see any reason why the interactive
compiler and the basis library need to share their standard i/o streams. That's
what happens with the existing implementations, but I don't see that the basis
library specification mandates it - couldn't a valid implementation of the
basis library bring up a separate window for its standard i/o?
So I think I side with Larry Paulson in viewing this as an instructive instance
where the programmer needs to distinguish between implementation-dependent
behaviour and behaviour that is guaranteed by the relevant specifications or
standards.
Regards,
Rob.
_______________________________________________
polyml mailing list
[email protected]
http://lists.inf.ed.ac.uk/mailman/listinfo/polyml