当 web.js 遇上 Eisa… Nodejs版探讨

当 web.js 遇上 Eisa… Nodejs版探讨

<p>鄙人的 <a href=“http://github.com/infinte/eisa”>Eisa</a> 虽说目前还很原始,但是基本上已经可以用了。基于 Necessaria 包管理器摆平客户端,Node 摆平服务器,你就可以结合 Eisa 语言的优点和无数已有的 JavaScript 类库,轮子不用造了,人参更美满了……</p> <br/> <br/><p>本文直接ネタ<a href=“http://cnodejs.org/blog/?p=1730”>小问的文章</a>,源码都是照抄来的,并换成了等价的 Eisa 形式。我省略了包导入的部分。</p> <br/> <br/><div class=“section”><h2>Backbone?很简单</h2><pre><span class=“comment”>// Eisa version by Belleve Invis</span> <br/> <br/><span class=“comment”>// Note that chained(f) returns a function.</span> <br/><span class=“comment”>// syntax:</span> <br/><span class=“comment”>// def f(x) = expression</span> <br/><span class=“comment”>// def f(x): statements end</span> <br/><span class=“keyword”>def</span> <span class=“identifier”>chained</span><span class=“punctor”>(</span><span class=“identifier”>f</span><span class=“punctor”>)</span> <span class=“operator”>=</span> <span class=“keyword function”>function</span><span class=“punctor”>:</span> <br/> <span class=“identifier”>f</span><span class=“punctor”>.</span><span class=“identifier”>apply</span> <span class=“keyword”>this</span><span class=“punctor”>,</span> <span class=“keyword”>arguments</span> <br/> <span class=“keyword flowctrl”>return</span> <span class=“keyword”>this</span> <br/><span class=“keyword”>end</span> <br/> <br/><span class=“comment”>// Model of Backbone</span> <br/><span class=“keyword”>def</span> <span class=“identifier”>Person</span> <span class=“operator”>=</span> <span class=“identifier”>Backbone</span><span class=“punctor”>.</span><span class=“identifier”>model</span><span class=“punctor”>.</span><span class=“identifier”>extent</span> <span class=“punctor”>{</span> <br/> <span class=“identifier”>sayHello</span><span class=“punctor”>:</span> <span class=“identifier”>chained</span> <span class=“punctor”>{</span> <span class=“identifier”>alert</span> <span class=“string literal”>“Hey, I’m “</span> <span class=“operator”>+</span> <span class=“operator”>@</span><span class=“identifier”>get</span><span class=“punctor”>(</span><span class=“string literal”>‘name’</span><span class=“punctor”>)</span> <span class=“operator”>+</span> <span class=“string literal”>”.”</span> <span class=“punctor”>}</span><span class=“punctor”>,</span> <br/> <span class=“identifier”>setName</span><span class=“punctor”>:</span> <span class=“identifier”>chained</span> <span class=“punctor”>{</span><span class=“operator”>|</span><span class=“identifier”>name</span><span class=“operator”>|</span> <br/> <span class=“operator”>@</span><span class=“identifier”>set</span> <span class=“punctor”>{</span><span class=“string literal”>‘name’</span><span class=“punctor”>:</span> <span class=“identifier”>name</span><span class=“punctor”>}</span> <br/> <span class=“identifier”>alert</span> <span class=“string literal”>“My name is “</span> <span class=“operator”>+</span> <span class=“operator”>@</span><span class=“identifier”>get</span><span class=“punctor”>(</span><span class=“string literal”>‘name’</span><span class=“punctor”>)</span> <span class=“operator”>+</span> <span class=“string literal”>”.”</span> <br/> <span class=“punctor”>}</span> <br/><span class=“punctor”>}</span> <br/> <br/><span class=“keyword”>var</span> <span class=“identifier”>Will</span> <span class=“operator”>=</span> <span class=“identifier”>Person</span><span class=“punctor”>.</span><span class=“identifier”>new</span><span class=“punctor”>(</span><span class=“punctor”>)</span> <br/><span class=“identifier”>Will</span> <span class=“operator”>|</span><span class=“punctor”>.</span><span class=“identifier”>setName</span> <span class=“string literal”>‘Will Wen Gunn’</span> <br/> <span class=“operator”>|</span><span class=“punctor”>.</span><span class=“identifier”>sayHello</span> <br/></pre></div><div class=“section”><h2>Mustache —— 做异步很简单啊!</h2><p>由于 Eisa 自带异步库和阻塞原语,所以就不用朴灵兄的 EventProxy 啦,直接上!</p> <br/><pre><span class=“comment”>// 注意:async 库是浏览器专用的</span> <br/><span class=“comment”>// 源码在 src/lib/async.js</span> <br/> <br/><span class=“keyword”>do</span> <span class=“identifier”>async</span><span class=“punctor”>.</span><span class=“identifier”>async</span> <span class=“punctor”>{</span> <br/> <span class=“keyword”>def</span> <span class=“identifier”>results</span> <span class=“operator”>=</span> <span class=“identifier”>async</span><span class=“punctor”>.</span><span class=“identifier”>join</span><span class=“punctor”>!</span> <span class=“punctor”>{</span> <br/> <span class=“identifier”>data</span><span class=“punctor”>:</span> <span class=“punctor”>{</span><span class=“operator”>|</span><span class=“identifier”>resend</span><span class=“operator”>|</span> <span class=“identifier”>$</span><span class=“punctor”>.</span><span class=“identifier”>getJSON</span><span class=“punctor”>(</span><span class=“identifier”>location</span><span class=“punctor”>.</span><span class=“identifier”>origin</span> <span class=“operator”>+</span> <span class=“string literal”>’/persons’</span><span class=“punctor”>,</span> <span class=“identifier”>resend</span><span class=“punctor”>)</span> <span class=“punctor”>}</span><span class=“punctor”>,</span> <br/> <span class=“identifier”>template</span><span class=“punctor”>:</span> <span class=“punctor”>{</span><span class=“operator”>|</span><span class=“identifier”>resend</span><span class=“operator”>|</span> <span class=“identifier”>$</span><span class=“punctor”>.</span><span class=“identifier”>get</span><span class=“punctor”>(</span><span class=“identifier”>location</span><span class=“punctor”>.</span><span class=“identifier”>origin</span> <span class=“operator”>+</span> <span class=“string literal”>’/tmpls/persons.html’</span><span class=“punctor”>,</span> <span class=“identifier”>resend</span><span class=“punctor”>)</span> <span class=“punctor”>}</span> <br/> <span class=“punctor”>}</span><span class=“punctor”>;</span> <br/> <span class=“identifier”>$</span><span class=“punctor”>(</span><span class=“string literal”>‘body’</span><span class=“punctor”>)</span><span class=“punctor”>.</span><span class=“identifier”>append</span> <span class=“identifier”>Mustache</span><span class=“punctor”>.</span><span class=“identifier”>to_html</span><span class=“punctor”>(</span><span class=“identifier”>results</span><span class=“punctor”>.</span><span class=“identifier”>template</span><span class=“punctor”>,</span> <span class=“identifier”>results</span><span class=“punctor”>.</span><span class=“identifier”>data</span><span class=“punctor”>)</span> <br/><span class=“punctor”>}</span> <br/></pre><p>相比 EventProxy,这里流程既简单又清楚。<pre><code>async.async</pre></code> 会处理包含异步调用(这里是 <pre><code>async.join</pre></code>,看那个感叹号)的代码块(这玩意叫阻塞原语),把它变成使用类似自动机的机构。<pre><code>async.join</pre></code> 会平行地启动多个任务并且聚合它们,结果会合成为一个对象“返回”。</p> <br/></div><div class=“section”><h2>Web.js 的 router</h2><pre><span class=“keyword”>def</span> <span class=“identifier”>urlRouter</span> <span class=“operator”>=</span> <span class=“punctor”>{</span> <br/> <span class=“string literal”>’^(\d{4})/(\d{2})/(\d{2})/(.*).jpg’</span><span class=“punctor”>:</span> <span class=“string literal”>’$1-$2-$3-$4.jpg’</span><span class=“punctor”>,</span> <br/> <span class=“string literal”>‘google’</span><span class=“punctor”>:</span> <span class=“string literal”>‘http://www.google.com’</span><span class=“punctor”>,</span> <br/> <span class=“string literal”>‘iwillwen’</span><span class=“punctor”>:</span> <span class=“string literal”>‘http://www.iwillwen.com’</span> <br/><span class=“punctor”>}</span> <br/><span class=“keyword”>def</span> <span class=“identifier”>getRouter</span> <span class=“operator”>=</span> <span class=“punctor”>{</span> <br/> <span class=“string literal”>’^getsomthing’</span><span class=“punctor”>:</span> <span class=“keyword function”>function</span><span class=“punctor”>(</span><span class=“identifier”>req</span><span class=“punctor”>,</span> <span class=“identifier”>res</span><span class=“punctor”>,</span> <span class=“identifier”>qs</span><span class=“punctor”>)</span><span class=“punctor”>:</span> <br/> <span class=“identifier”>res</span><span class=“punctor”>.</span><span class=“identifier”>sendJSON</span> <span class=“identifier”>qs</span> <br/> <span class=“keyword”>end</span><span class=“punctor”>,</span> <br/> <span class=“string literal”>’^car’</span><span class=“punctor”>:</span> <span class=“keyword function”>function</span><span class=“punctor”>(</span><span class=“identifier”>req</span><span class=“punctor”>,</span> <span class=“identifier”>res</span><span class=“punctor”>,</span> <span class=“identifier”>qs</span><span class=“punctor”>)</span><span class=“punctor”>:</span> <br/> <span class=“keyword flowctrl”>case</span> <span class=“identifier”>qs</span><span class=“punctor”>.</span><span class=“identifier”>action</span><span class=“punctor”>:</span> <br/> <span class=“keyword flowctrl”>when</span> <span class=“string literal”>‘foo’</span><span class=“punctor”>:</span> <span class=“identifier”>res</span><span class=“punctor”>.</span><span class=“identifier”>send</span> <span class=“string literal”>‘Your action is foo’</span> <br/> <span class=“keyword flowctrl”>when</span> <span class=“string literal”>‘bar’</span><span class=“punctor”>:</span> <span class=“identifier”>res</span><span class=“punctor”>.</span><span class=“identifier”>send</span> <span class=“string literal”>‘Your action is bar’</span> <br/> <span class=“keyword”>end</span> <br/> <span class=“keyword”>end</span> <br/><span class=“punctor”>}</span> <br/><span class=“keyword”>def</span> <span class=“identifier”>postRouter</span> <span class=“operator”>=</span> <span class=“punctor”>{</span> <br/> <span class=“string literal”>’^postsomthing’</span><span class=“punctor”>:</span> <span class=“keyword function”>function</span><span class=“punctor”>(</span><span class=“identifier”>req</span><span class=“punctor”>,</span> <span class=“identifier”>res</span><span class=“punctor”>,</span> <span class=“identifier”>data</span><span class=“punctor”>)</span><span class=“punctor”>:</span> <br/> <span class=“identifier”>res</span><span class=“punctor”>.</span><span class=“identifier”>sendJSON</span> <span class=“identifier”>qs</span> <br/> <span class=“keyword”>end</span><span class=“punctor”>,</span> <br/> <span class=“string literal”>’^car’</span><span class=“punctor”>:</span> <span class=“keyword function”>function</span><span class=“punctor”>(</span><span class=“identifier”>req</span><span class=“punctor”>,</span> <span class=“identifier”>res</span><span class=“punctor”>,</span> <span class=“identifier”>data</span><span class=“punctor”>)</span><span class=“punctor”>:</span> <br/> <span class=“keyword flowctrl”>case</span> <span class=“identifier”>data</span><span class=“punctor”>.</span><span class=“identifier”>action</span><span class=“punctor”>:</span> <br/> <span class=“keyword flowctrl”>when</span> <span class=“string literal”>‘foo’</span><span class=“punctor”>:</span> <span class=“identifier”>res</span><span class=“punctor”>.</span><span class=“identifier”>send</span> <span class=“string literal”>‘Your action is foo’</span> <br/> <span class=“keyword flowctrl”>when</span> <span class=“string literal”>‘bar’</span><span class=“punctor”>:</span> <span class=“identifier”>res</span><span class=“punctor”>.</span><span class=“identifier”>send</span> <span class=“string literal”>‘Your action is bar’</span> <br/> <span class=“keyword”>end</span> <br/> <span class=“keyword”>end</span> <br/><span class=“punctor”>}</span> <br/> <br/><span class=“identifier”>web</span><span class=“punctor”>.</span><span class=“identifier”>run</span> <span class=“identifier”>urlRouter</span><span class=“punctor”>,</span> <span class=“number literal”>80</span> <br/> <span class=“operator”>|</span><span class=“punctor”>.</span><span class=“identifier”>get</span> <span class=“identifier”>getRouter</span> <br/> <span class=“operator”>|</span><span class=“punctor”>.</span><span class=“identifier”>post</span> <span class=“identifier”>postRouter</span><span class=“punctor”>;</span> <br/> <br/><span class=“identifier”>console</span><span class=“punctor”>.</span><span class=“identifier”>log</span> <span class=“string literal”>‘The app is running on http://localhost’</span> <br/> <br/></pre><p>从案例可以看出,第一,因为 Eisa 有真正的常量,原先很多用 var 的“常量”如今有了名分;第二,Eisa 的函数可以省略括弧,进一步减少冗余的字符数;第三,Eisa 的多路分支没有贯穿(fall through),语义更加明确。</p> <br/> <br/><p>各位可以去 <a href=“http://github.com/infinte/eisa”>http://github.com/infinte/eisa</a> 来围观我的项目。</p>


3 回复

当 web.js 遇上 Eisa… Nodejs版探讨

鄙人的 Eisa 虽说目前还很原始,但是基本上已经可以用了。基于 Necessaria 包管理器摆平客户端,Node 摆平服务器,你就可以结合 Eisa 语言的优点和无数已有的 JavaScript 类库,轮子不用再造了,人参更美满了……

本文直接ネタ小问的文章,源码都是照抄来的,并换成了等价的 Eisa 形式。我省略了包导入的部分。

Backbone?很简单

// Eisa version by Belleve Invis
// Note that chained(f) returns a function.
// syntax:
//     def f(x) = expression
//     def f(x): statements end

def chained(f):
    f.apply(this, arguments)
    return this
end

// Model of Backbone
def Person = Backbone.model.extent {
    sayHello: chained {
        alert("Hey, I'm " + @get('name') + ".")
    },
    setName: chained |name|
        @set({'name': name})
        alert("My name is " + @get('name') + ".")
    end
}

var Will = Person.new()
Will |.setName 'Will Wen Gunn'
     |.sayHello

Mustache —— 做异步很简单啊!

由于 Eisa 自带异步库和阻塞原语,所以就不用朴灵兄的 EventProxy 啦,直接上!

// 注意:async 库是浏览器专用的
// 源码在 src/lib/async.js

do async {
    def results = async.join! {
        data: $getJSON(location.origin + '/persons', resend),
        template: $get(location.origin + '/tmpls/persons.html', resend)
    }
    $('body').append(Mustache.to_html(results.template, results.data))
}

相比 EventProxy,这里流程既简单又清楚。async.async 会处理包含异步调用(这里是 async.join,看那个感叹号)的代码块(这玩意叫阻塞原语),把它变成使用类似自动机的机构。async.join 会平行地启动多个任务并且聚合它们,结果会合成为一个对象“返回”。

Web.js 的 router

def urlRouter = {
    '^(\d{4})/(\d{2})/(\d{2})/(.*).jpg': '$1-$2-$3-$4.jpg',
    'google': 'http://www.google.com',
    'iwillwen': 'http://www.iwillwen.com'
}

def getRouter = {
    '^getsomthing': function(req, res, qs):
        res.sendJSON(qs)
    end,
    '^car': function(req, res, qs):
        case qs.action:
            when 'foo': res.send('Your action is foo')
            when 'bar': res.send('Your action is bar')
        end
    end
}

def postRouter = {
    '^postsomthing': function(req, res, data):
        res.sendJSON(data)
    end,
    '^car': function(req, res, data):
        case data.action:
            when 'foo': res.send('Your action is foo')
            when 'bar': res.send('Your action is bar')
        end
    end
}

web.run   urlRouter, 80
   |.get  getRouter
   |.post postRouter;

console.log 'The app is running on http://localhost'

从案例可以看出,第一,因为 Eisa 有真正的常量,原先很多用 var 的“常量”如今有了名分;第二,Eisa 的函数可以省略括弧,进一步减少冗余的字符数;第三,Eisa 的多路分支没有贯穿(fall through),语义更加明确。

各位可以去 http://github.com/infinte/eisa 来围观我的项目。


我对语言无所谓,不过确实懒得学一门为了语言而语言的语言。

根据您提供的内容,“当 web.js 遇上 Eisa… Nodejs版探讨” 这个帖子主要讨论了如何在 Eisa 语言中使用 Backbone 和 Mustache 库,以及如何定义路由处理程序。Eisa 是一种新的编程语言,其语法设计简化了代码编写,并且支持异步操作和模型绑定等功能。

示例代码解释

Backbone Model 示例

// Eisa version by Belleve Invis
// Note that chained(f) returns a function.
// syntax:
//     def f(x) = expression
//     def f(x): statements end

def chained(f) = function :
    f.apply(this, arguments)
    return this
end

// Model of Backbone
def Person = Backbone.model.extent {
    sayHello: chained {
        alert("Hey, I'm " + @get('name') + ".")
    },
    setName: chained {
        |name|
        @set({'name': name})
        alert("My name is " + @get('name') + ".")
    }
}

var Will = Person.new()
Will |.setName 'Will Wen Gunn'
     |.sayHello

这里定义了一个 Person 模型,它包含两个方法:sayHellosetName。这两个方法都使用了 chained 函数来实现链式调用。chained 函数确保每次调用后都能返回 this 对象,使得方法调用可以链式进行。

Web.js 路由示例

def urlRouter = {
    '^(\d{4})/(\d{2})/(\d{2})/(.*).jpg': '$1-$2-$3-$4.jpg',
    'google': 'http://www.google.com',
    'iwillwen': 'http://www.iwillwen.com'
}

def getRouter = {
    '^getsomthing': function(req, res, qs):
        res.sendJSON(qs)
    end,
    '^car': function(req, res, qs):
        switch qs.action:
            when 'foo': res.send('Your action is foo')
            when 'bar': res.send('Your action is bar')
        end
    end
}

def postRouter = {
    '^postsomthing': function(req, res, data):
        res.sendJSON(data)
    end,
    '^car': function(req, res, data):
        switch data.action:
            when 'foo': res.send('Your action is foo')
            when 'bar': res.send('Your action is bar')
        end
    end
}

web.run   urlRouter, 80
   |.get  getRouter
   |.post postRouter;

console.log 'The app is running on http://localhost'

在这个例子中,urlRouter 定义了几个 URL 映射规则。getRouterpostRouter 分别定义了 GET 和 POST 请求的处理程序。通过管道符 |. 来设置不同的 HTTP 方法,使得路由配置非常清晰。

总结

Eisa 语言通过简化语法、引入链式调用等方式提高了代码的可读性和可维护性。上述示例展示了如何在 Eisa 中使用 Backbone 和 Mustache 库,以及如何设置路由处理程序,使得代码结构清晰且易于理解。

回到顶部