Есть ли у SML (Poly) CL-подобный REPL? - PullRequest
4 голосов
/ 04 марта 2012

Вот цитата из «Лиспинга в JPL» Рона Гаррета:

«Отладка программы, работающей на оборудовании стоимостью 100 миллионов долларов, которое находится на расстоянии 100 миллионов миль, является интересным опытом.Цикл печати, запущенный на космическом корабле, оказался неоценимым в поиске и устранении проблемы. "

Как новичок, пытающийся решить, где прыгать, я склоняюсь к ML, потому что бывший профессор бредил, и я нахожу многокниги, которые объединяют обсуждения Lambda Calculus с ML и ML, выглядят довольно вменяемыми.(В конце концов я собираюсь научить этому.)

Итак, есть ли у ML REPL, где, подобно Лиспу, вы можете просто «добавить больше кода», когда он работает, то есть, может стоить $ 100 миллионов мистеру Гаррету?аппаратного обеспечения работало на ML?

Ответы [ 2 ]

5 голосов
/ 01 марта 2013

Poly / ML запускается с REPL по умолчанию, что аналогично SML / NJ. Более того, вы можете легко вызывать компилятор во время выполнения: он создаст для вас собственный код и добавит его в среду ML способом eval в LISP, но это статически типизированный и реальный машинный код, а не интерпретируемый.

Структура PolyML.Compiler предоставляет различные (относительно стабильные) интерфейсы для этого, помимо официального стандарта SML.

Вот рабочий пример для Poly / ML 5.5 или 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;

Теперь мы можем вызвать это в обычном Poly / ML REPL следующим образом:

> 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

Это дает вам метапрограммирование в стиле LISP в статически типизированном мире SML.

Обратите внимание, что структура PolyML.Compiler имеет дополнительные параметры для управления поведением вызова компилятора во время выполнения. Об этом лучше спросить в списке рассылки polyml.

2 голосов
/ 04 марта 2012

PolyML имеет REPL. Я не знаю его подробностей, но если он похож на SML / NJ, вы не сможете использовать его для запуска работающей программы. Если вы хотите сделать это, Common Lisp или Squeak - ваши лучшие ставки - большинство остального сообщества языков программирования считает, что обновлять живую программу нужно как плохую (или, по крайней мере, слишком опасную) программу. Идея-иметь-по-умолчанию).

Но выучите Стандарт МЛ. На мой взгляд, это канонический функциональный язык. понимание этого позволяет легко понять, почему функциональное программирование является мощным, а также помогает понять весь спектр языков функционального программирования по их отклонениям от него.

...