Ocaml 在脚本中定义闭包变量

Ocaml 在脚本中定义闭包变量,ocaml,interop,ffi,bucklescript,Ocaml,Interop,Ffi,Bucklescript,我正在尝试将下面的ES6脚本转换为bucklescript,但我一辈子都不知道如何在bucklescript中创建“闭包” 从“phoenix”导入{Socket,Presence} 让套接字=新套接字(“/socket”{ 参数:{user_id:window.location.search.split(“=”[1]} }) let channel=socket.channel(“房间:大厅”{}) 让状态=新状态(通道) 功能renderOnlineUsers(状态){ let respon

我正在尝试将下面的ES6脚本转换为bucklescript,但我一辈子都不知道如何在bucklescript中创建“闭包”

从“phoenix”导入{Socket,Presence}
让套接字=新套接字(“/socket”{
参数:{user_id:window.location.search.split(“=”[1]}
})
let channel=socket.channel(“房间:大厅”{})
让状态=新状态(通道)
功能renderOnlineUsers(状态){
let response=“”
presence.list((id,{metas:[first,…rest]})=>{
让计数=rest.length+1
响应+=`
${id}(计数:${count})
` }) document.querySelector(“main[role=main]”)。innerHTML=response } socket.connect() presence.onSync(()=>renderOnlineUsers(presence)) channel.join()
我无法明确指出的部分是
let response=“”
(在本例中是var,因为bucklescript总是使用
var
s):

函数renderOnlineUsers(状态){
let response=“”
presence.list((id,{metas:[first,…rest]})=>{
让计数=rest.length+1
响应+=`
${id}(计数:${count})
` }) document.querySelector(“main[role=main]”)。innerHTML=response }
到目前为止,我得到的最接近的结果不包括
结果
声明

。。。
...
让我们来同步ev=
让result=”“输入
让listFunc=[%raw begin
{|
(id,{metas:[first,…rest]})=>{
让计数=rest.length+1
结果+=`${id}(计数:${count})\n`
}
|}
结束
]在
让我们=
在场。中的listPresence(listFunc)
[%raw{| console.log(result)|}]
...
...
汇编至:

显示同步功能(ev){
var listFunc=(
(id,{metas:[first,…rest]})=>{
让计数=rest.length+1
结果+=`${id}(计数:${count})\n`
}
);
状态列表(listFunc);
返回(console.log(result));
}

结果作为优化被删除,因为它被认为是未使用的。使用依赖于BuckleScript生成的代码的
raw
代码通常不是一个好主意,因为在生成的代码中可能会遇到很多意外情况

对编译器认为不可变的变量进行变异也不是一个好主意,因为它将基于值永远不会改变的假设执行优化

这里最简单的修复方法是将
[%raw{{console.log(result)}]
替换为
Js.log result
,但看看如何在OCaml中编写
listFunc
可能会有所启发:

let onpresence同步ev=
让result=ref“”输入
让listFunc=fun[@bs]id项->
让count=Js.Array.length项##元插入
结果:={j|$id(count:$count)\n|j}
在里面
让uu=presence |。(listPresence listFunc)位于
Js.log!结果

请注意,
result
现在是一个
ref
单元格,这就是在OCaml中指定可变变量的方式
ref
单元格使用
更新:=
并使用
检索其包含的值。另请注意
[@bs]
注释,该注释用于指定传递给外部高阶函数的函数所需的参数。使用的字符串插值语法:
{j|…|j}

太棒了!是的,我知道要避免生食,这正是我发布的原因。我对OCaml和Bucklescript还是新手。我不知道
ref
,谢谢!作为一个附带问题,分解数组或对象的等效方法是什么?(示例js:
{metas:[first,…rest]}=obj
实际上没有等价物,因为OCaml中的模式是静态的,不会创建新的值。它们只是绑定到现有值的一部分。因此,您可以使用类似于
[|a,b |]的模式。)
它匹配两个元素的数组,但不能有一个需要将旧数组的元素复制到新数组中的数组。你也不能分解对象,因为它们也是动态的。你通常使用的是记录和列表,它们的工作方式与你在这里期望的完全相同。不幸的是,这对JavaScript互操作没有帮助因为JavaScript没有记录和列表,所以它有对象和数组。不幸的是,你只能用老式的方式来做。