【问题标题】:Does SML (Poly) have a CL-like REPL?SML (Poly) 是否有类似 CL 的 REPL?
【发布时间】:2012-03-22 06:48:57
【问题描述】:

这是 Ron Garret 的“JPL 的 Lisping”中的一句话:

“调试在 1 亿英里外的价值 1 亿美元硬件上运行的程序是一种有趣的体验。在航天器上运行读取-评估-打印循环证明对于发现和解决问题非常宝贵。”

作为一个试图决定从哪里跳入的初学者,我倾向于 ML,因为前任教授对此很感兴趣,而且我发现许多将 Lambda 微积分讨论与 ML 相结合的书籍,并且 ML 看起来相当理智。 (我最终会教这个。)

那么,ML 是否有一个 REPL,就像 Lisp 一样,您可以在它运行时“添加更多代码”,即 Garret 先生价值 1 亿美元的硬件能否在 ML 上运行?

【问题讨论】:

  • 我建议阅读 Poly/ML 的文档。
  • ... 在该文档的某处它会说“是的,我们有一个 REPL 就像 CL 一样,你总是可以有一个正在运行的程序 and and and”?不,我怀疑。我需要问问知道的人。
  • 文档是人工编写的。是的,我希望它会记录您与它的交互方式。安装软件并对其进行测试是另一种方式。我也很确定它有一个邮件列表。我怀疑您是否会在 Stackoverflow 上找到 Poly/ML 实际用户的更好答案。其实我怀疑这是一个真正的问题。

标签: common-lisp read-eval-print-loop ml


【解决方案1】:

Poly/ML 默认以 REPL 启动,类似于 SML/NJ。此外,您可以在运行时轻松调用编译器:它会为您生成本机代码并以 LISP 中eval 的方式将其添加到 ML 环境中,但它是静态类型和真实机器代码,而不是解释代码。

结构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

这为您在 SML 的静态类型世界中提供 LISP 风格的元编程。

请注意,结构 PolyML.Compiler 具有更多选项来控制运行时编译器调用的行为。最好在 polyml 邮件列表中询问。

【讨论】:

    【解决方案2】:

    PolyML 有一个 REPL。我不知道它的细节,但如果它类似于 SML/NJ,你将无法在它运行时使用它来敲击正在运行的程序。如果你想这样做,Common Lisp 或 Squeak 是你最好的选择——大多数编程语言社区的其他人都认为更新实时程序的想法是因为它运行得很糟糕(或者至少太危险了-have-available-by-default) 想法。

    但一定要学习标准机器学习。在我看来,它是规范的函数式语言。理解它可以很容易地理解为什么函数式编程很强大,并且还可以帮助您了解函数式编程语言的所有偏差。

    【讨论】:

    • Erlang 就是这样做的。 Java 现在有各种尝试帮助实时更新的工具。参见例如 OSGi。
    • 并将 Clojure 也加入其中。
    猜你喜欢
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    相关资源
    最近更新 更多