Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将简单的命令行OCaml脚本编译成Javascript_Javascript_Ocaml_Js Of Ocaml - Fatal编程技术网

如何将简单的命令行OCaml脚本编译成Javascript

如何将简单的命令行OCaml脚本编译成Javascript,javascript,ocaml,js-of-ocaml,Javascript,Ocaml,Js Of Ocaml,我有一个简单的命令行OCaml应用程序,它在Sys.argv.(1)上执行计算,并将结果输出到stdout。我可以用js\u of_ocaml将它编译成Javascript,但是它给了我很多关于caml\u output\u char未定义的错误。我通过删除printfs修复了这些错误,因此它可以运行,但在运行时会冻结firefox 如何将简单的OCaml命令行脚本干净地编译成基于Javascript的网页;在不维护分叉版本或冻结浏览器的情况下?您可能会希望使用webworkers,因为在UI线

我有一个简单的命令行OCaml应用程序,它在
Sys.argv.(1)
上执行计算,并将结果输出到stdout。我可以用
js\u of_ocaml
将它编译成Javascript,但是它给了我很多关于
caml\u output\u char
未定义的错误。我通过删除printfs修复了这些错误,因此它可以运行,但在运行时会冻结firefox


如何将简单的OCaml命令行脚本干净地编译成基于Javascript的网页;在不维护分叉版本或冻结浏览器的情况下?

您可能会希望使用webworkers,因为在UI线程中运行不是围绕Javascript协同多任务设计的软件可能会导致浏览器锁定。 您可以将以下头添加到OCaml文件的顶部,以重载正常的OCaml系统和打印实现

(* JsHeader.ml *)
let output_buffer_ = Buffer.create 1000
let flush x=let module J = Js.Unsafe in let () = J.call 
        (J.variable "postMessage") (J.variable "self")
        [|J.inject (Js.string (Buffer.contents output_buffer_))|]
     in Buffer.clear output_buffer_

let print_string = Buffer.add_string output_buffer_
let print_char = Buffer.add_char output_buffer_
let print_newline () = print_char '\n'
let print_endline s = print_string (s^"\n"); flush ()
let caml_ml_output_char = print_char
let printf fmt = Printf.bprintf output_buffer_ fmt
module Printf = struct
    include Printf
    let printf fmt = Printf.bprintf output_buffer_ fmt
end
传入命令行参数的最自然的方式是通过发送给web工作者的URL。我们可以重写Ocaml Sys模块,将
?argv
读取为以null结尾的字符串序列

module Sys = struct
    let char_split delim s = (*Str.split is overkill*)
        let hd = ref "" in let l = ref [] in 
        String.iter (fun c -> 
            if c = delim
            then  (l := (!hd)::(!l); hd := "")
            else hd := (!hd) ^ (String.make 1 c)
        ) s;
        List.rev ((!hd)::(!l)) 
    let getenv x = List.assoc x Url.Current.arguments
    let argv = Array.of_list (char_split '\x00' (getenv "?argv"))
    let executable_name = argv.(0)
end
现在我们已经输入了标题,我们可以输入一个简单的OCaml命令行程序:

(* cli.ml *)
let _ = print_string (Array.fold_left (^) "" (Array.make 40 (String.lowercase (Sys.argv.(1)^"\n"))) )
这个命令行程序依赖操作系统刷新输出,但我们必须手动刷新输出。 您可能还希望发送一个空字符,以便Javascript知道命令已完成。 这可以通过添加以下页脚来实现

(* JsFooter.ml *)
let _ = flush stdout; print_endline "\x00" 
我们可以按如下方式连接文件并编译它们:

 cat JsHeader.ml cli.ml JsFooter.ml > merged.ml
 ocamlbuild -use-menhir -menhir "menhir" \
   -pp "camlp4o -I /opt/local/lib/ocaml/site-lib js_of_ocaml/pa_js.cmo" \
   -cflags -I,+js_of_ocaml,-I,+site-lib/js_of_ocaml -libs js_of_ocaml \
   -lflags -I,+js_of_ocaml,-I,+site-lib/js_of_ocaml merged.byte
 js_of_ocaml merged.byte
现在我们已经创建了文件merged.js,我们可以将javascript封装在一个简单的网页中,如下所示:

<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml+xml; charset=UTF-8" />
<title>ml2js sample_cli</title>
<script type="text/javascript">
<!--
var worker;
function go () {
  var output=document.getElementById ("output");
  var argv = encodeURIComponent("/bin/sample_cli\0"+document.getElementById ("input").value);
  if (worker) {
    worker.terminate();
  }
  worker = new Worker ("sample_cli.js?argv="+argv);
  document.getElementById ("output").value="";
  worker.onmessage = function (m) {
    if (typeof m.data == 'string') {
    if (m.data == "\0\n") {
        output.scrollTop = output.scrollHeight
    } else {
        output.value+=m.data;
    }
    }
  }
}
//-->
</script>
</head>

<body onload=go()>
<textarea id="input" rows="2" cols="60" onkeyup="go()" onchange="go()" style="width:90%">SAMPLE_INPUT</textarea> 
<button onclick="go()">go</button><br>
<textarea id="output" rows="0" cols="60" style="width:100%;height:90%" readonly onload=go()>
Your browser does not seem to support Webworkers.
Try Firefox, Chrome or IE10+. 
</textarea>
</body>

</html>

ml2js示例\u cli
样本输入
去
您的浏览器似乎不支持Webworkers。 试试Firefox、Chrome或IE10+。

有关此方法的实际示例,以及附加适当页眉、页脚等的脚本,请参见。

您使用的是什么js_of_ocaml版本?caml\u ml\u output\u char不应出现错误。在节点上运行时,应正确设置sys.argv。在浏览器中,Sys.argv设置为[|“a.out”|]。
如果您对此仍有疑问,请在上打开GitHub问题。

我正在Ubuntu上使用1.4-1build1。即使最新版本的
js\u of_ocaml
在清除例如Sys.argv方面做得更好,我仍然需要像上面一样包装我的ml脚本,使其在浏览器中真正有用?(顺便说一句,这可能是一个更好的评论,而不是一个答案?)我已经修改了我的问题,提到我特别感兴趣的网页。