Does SML (Poly) have a CL-like REPL?
Asked Answered
C

2

5

Here's a quote from Ron Garret's "Lisping at JPL":

"Debugging a program running on a $100M piece of hardware that is 100 million miles away is an interesting experience. Having a read-eval-print loop running on the spacecraft proved invaluable in finding and fixing the problem."

As a beginner trying to decide where to jump in, I am leaning towards ML because a former prof raved about and I'm finding many books that integrate Lambda Calculus discussions with ML and ML looks fairly sane. (I'm eventually going to teach this.)

So, does ML have a REPL where, like Lisp, you can just "add more code" as it's running, i.e., could Mr. Garret's $100M piece of hardware been running on ML?

Capercaillie answered 4/3, 2012 at 14:45 Comment(3)
I propose to read the documentation of Poly/ML.Sulphurate
... and somewhere in that documentation it will say "Yes, we have a REPL just like CL and you can always have a running program and and and"? No, I doubt it. I need to ask humans that know.Capercaillie
the documentation is written by humans. Yes, I expect that it will document how you interact with it. Installing the software and testing it is another way. I'm also pretty sure that there is a mailing list for it. I doubt that you find better answers of actual users of Poly/ML on Stackoverflow. Actually I doubt that this is a real question.Sulphurate
W
7

Poly/ML starts up with REPL by default, which is similar to SML/NJ. Moreover, you can invoke the compiler easily at runtime: it will produce native code for you and add it to the ML environment in the manner of eval in LISP, but it is statically typed and real machine code, not interpreted one.

The structure PolyML.Compiler provides various (relatively stable) interfaces to do that, beyond the official SML standard.

Here is a worked example for Poly/ML 5.5 or 5.6:

fun eval text =
  let
    fun print s = (TextIO.output (TextIO.stdOut, s); TextIO.flushOut TextIO.stdOut);

    val line = ref 1;
    val in_buffer = ref (String.explode text);
    val out_buffer = ref ([]: string list);

    fun output () = String.concat (rev (! out_buffer));

    fun get () =
      (case ! in_buffer of
        [] => NONE
      | c :: cs => (in_buffer := cs; if c = #"\n" then line := ! line + 1 else (); SOME c));
    fun put s = out_buffer := s :: ! out_buffer;
    fun put_message {message = msg1, hard, location = {startLine = line, ...}, context} =
     (put (if hard then "Error: " else "Warning: ");
      PolyML.prettyPrint (put, 76) msg1;
      (case context of NONE => () | SOME msg2 => PolyML.prettyPrint (put, 76) msg2);
      put ("Line " ^ Int.toString line ^ "\n"));

    val parameters =
     [PolyML.Compiler.CPOutStream put,
      PolyML.Compiler.CPErrorMessageProc put_message,
      PolyML.Compiler.CPLineNo (fn () => ! line)];
    val _ =
      (while not (List.null (! in_buffer)) do
        PolyML.compiler (get, parameters) ())
      handle exn =>
        (put ("Exception- " ^ General.exnMessage exn ^ " raised");
          print (output ()); raise exn);
  in print (output ()) end;

Now we can invoke this at the normal Poly/ML REPL like this:

> eval "1 + 1";
val it = 2: int
val it = (): unit
> eval "fun f 0 = 1 | f n = n * f (n - 1)";
val f = fn: int -> int
val it = (): unit
> eval "f 42";
val it = 1405006117752879898543142606244511569936384000000000: int
val it = (): unit
> f 42;
val it = 1405006117752879898543142606244511569936384000000000: int

This gives you LISP-style meta-programming in the statically typed world of SML.

Note that structure PolyML.Compiler has further options to control the behaviour of the runtime compiler invocation. Better ask at the polyml mailing list about it.

Warman answered 1/3, 2013 at 16:52 Comment(0)
S
3

PolyML has a REPL. I don't know its details, but if it's similar to SML/NJ, you won't be able to use it to bang on a running program as it's running. If you want to do that, Common Lisp or Squeak are your best bets -- most of the rest of the programming-languages community views the idea of updating a live program as it's running as a bad (or at least too-dangerous-to-have-available-by-default) idea.

But do learn Standard ML. In my mind, it is the canonical functional language. understanding it makes it easy to understand why functional programming is powerful, and also helps you understand the whole spectrum of functional programming languages by their deviations from it.

Statuary answered 4/3, 2012 at 16:9 Comment(2)
Erlang does that. Java now has various tools that try to help with live updates. See for example OSGi.Sulphurate
And add Clojure to the mix too.Vedda

© 2022 - 2024 — McMap. All rights reserved.