自宣布LunaScript(http://www.asana.com/luna)以来,我一直对它感到好奇,我想在这里调查一下哪些现有工具与之类似,特别是积极开发/维护的软件。从博客文章:
感兴趣的主要功能是响应式(Reactive)编程/增量评估/双向数据绑定(bind)/无论您要调用什么,但跨越浏览器,应用服务器和RDBMS ,可以通过为每个平台生成代码单个高级程序。
最佳答案
更新11年7月10日:在底部查看我的要点。
概观
我的外卖
乐趣
乐趣是与我所理解的Lunascript最为接近的语言。特别地,功能性响应式(Reactive)编程超越了客户端-服务器和服务器-数据库的划分,使您可以创建直接以持久性数据库状态表示的UI元素,并使它们随着数据库状态的变化而动态更新。从chat示例中,请注意在将消息追加到全局消息集(使用send按钮)后,如何动态更新循环生成的消息列表:
<div class="chat">
<input data=userInput class="messageInput"/>
<button>"Send"</button onClick=handler() {
let newMessage = new { text: userInput }
userInput.set("")
global.messages.unshift(newMessage)
}>
<div class="messages">
for (message in global.messages) {
<div class="message"> message.text </div>
}
</div>
</div>
那几乎是一个完整的聊天应用程序! (对一些声明行取模。)
但是,该项目仍处于初期阶段,尚不完善,语言仍在不断变化。而且,我仍然对以下问题有疑问:明确控制动态更新与静态更新,服务器上运行的内容,发生多少通信等有多么容易。当然,这种方法的可扩展性如何。作者似乎在闲暇时开发这个项目。
Ur/Web
Ur(一种ML风格的编程语言)和Ur/Web(用于Ur的网络框架)给我留下了深刻的印象。 Ur拥有一个具有从属类型的类型系统,但是进行了更为传统的类型检查,从而避免了要求用户提供证明帮助。相反,从属类型提供了元编程框架,使您可以编写一个CRUD应用程序,该应用程序通常为任何复合数据类型(数据库模式)生成 View 。但是,虽然Ur/Web具有客户端响应式(Reactive)编程功能,但客户端-服务器/AJAX通信是明确的。例如,在incrementing counter示例中,还需要用于更新计数器的RPC调用来获取更新的计数器值(尽管一旦设置了客户端
src
变量,该 View 就会动态更新):sequence seq
fun increment () = nextval seq
fun main () =
src <- source 0;
return <xml><body>
<dyn signal={n <- signal src; return <xml>{[n]}</xml>}/>
<button value="Update" onclick={n <- rpc (increment ()); set src n}/>
</body></xml>
请注意,这仅在您按下按钮时更新计数器,而在其他人更新计数器时不更新,这是一种有趣的聊天应用程序所显示的 react 。
作者认为Ur/Web已准备好用于生产,并提供咨询/支持服务。尽管看似手工计数,但仍有一些Ur/web用户在野外。
链接
Links是Philip Wadler小组的一个项目。我很惊讶地发现它不提供任何形式的功能性响应式(Reactive)编程,并且诸如DOM操作之类的事情势在必行。对于客户端-服务器通信,我们同样具有显式RPC。我认为Links与GWT有点相似,因为它只是一种可以生成服务器和客户端代码的语言(具有 flavor ),特别是使您免受JavaScript的攻击。作为这种屏蔽的一个示例,链接为客户端并发进程提供了显式的消息传递通信(特别是参与者)。这些在编写阻止代码(例如RPC)而不会导致整个客户端应用程序阻止的情况下非常有用。
以下代码来自其updatable autocompletion demo(source),这是一个应用程序,其中列出了您所键入的单词的数据库支持的补全,并且可以插入新的补全。从UI开始,我们有一个文本框,完成列表和一个新定义的表单:
<form l:onkeyup="{handler!Suggest(s)}">
Search: <input type="text" l:name="s" autocomplete="off"/>
</form>
<div id="suggestions"/>
<h3>New definition</h3>
<div id="add">
{addForm(handler)}
</div>
handler
是在客户端运行的actor,它代表UI阻止RPC: var handler = spawn {
fun receiver(s) {
receive {
case Suggest(s) -> suggest(s); receiver(s)
case NewDef(def) ->
newDef(def);
replaceChildren(addForm(self()), getNodeById("add"));
if (s <> "") suggest(s) else (); receiver(s)
}
}
receiver("")
};
因此,
handler!Suggest(s)
将Suggest
消息发送到handler
。注意NewDef
处理程序还需要记住如何更新完成列表(通过调用suggest
,就像Suggest
处理程序一样)以使完成与数据库中的内容保持同步。suggest
函数要求服务器查询数据库,然后强制更新DOM:fun suggest(s) client {
replaceChildren(format(completions(s)), getNodeById("suggestions"))
}
fun completions(s) server {
if (s == "") []
else {
query [10] {
for (def <-- defsTable)
where (def.word =~ /^{s}.*/)
orderby (def.word)
[def]
}
}
}
请注意这些函数是如何注释的以及它们应在何处运行。
这不是正在积极开发中。
迅速
Swift与GWT非常相似,但是具有自动代码分区功能。这个想法是,您可以将某些数据“ anchor 定”到服务器端(其动机是为了安全,因此本文将所有内容都表述为信息流控制问题),然后分区程序根据代码和使用由大量关于边缘成本的静态试探法驱动的最小切割。它并不是真正专注于语言/表达能力,因此其中的编程显然只是编写GWT,系统在其中为每行代码确定是在客户端还是在服务器上运行。这不是正在积极开发中。