MoonScript

这是一个关于MoonScript的博客

MoonScript简介

作者:糖果

Coffescript是一种中间的脚本,可以把这种脚本翻译成JavaScript。而MoonScript,是可以翻译成lua语言的中间脚本。

本文简单的介绍的:

  1. 如何在VIM中,实现MoonScript语法高亮。
  2. 如何简单的编译MoonScript脚本。
  3. MoonScript面向对象OO简介。

1.安装MoonScript

sudo luarocks install moonscript

2.创建.moon源文件

app.moon

lapis = require "lapis"   
class extends lapis.Application   
  "/": => 
"Welcome to Lapis #{require "lapis.version"}!" 

3.安装MoonScript语法高亮的插件。

3-1.下载vim的bundle插件管理程序。

git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle

3-2.创建.vimrc配置文件。

vim ~/.vimrc

3-3. 编辑.vimrc文件内容。

set nocompatible                                                                                                                      
filetype off                                                                                                                          
set rtp+=~/.vim/bundle/vundle/                                                                                                        
call vundle#rc()                                                                                                                                      
Bundle 'leafo/moonscript-vim'                                                                                                         
syntax enable 

3-4.进入VIM,安装bundle插件。

vim +BundleInstall

3-5.翻译成lua脚本,并运行。

moonc app.moon
lua app.lua

按照如上步骤操作后:

  1. 可以用moonc命令翻译.moon脚本到.lua脚步。
  2. vim支持moonscript的语法高亮检查。

Moonscript与OO面向对象:

讲MoonScript不能不提她对OO面向对像的支持,下面简单介绍一下MoonScirpt面像对像的 特性。对向函数与变量的封装,MoonScirpt的函数定义有其独特的地方是。

foo = ->
    print "foo"
    
foo()    --函数调用

上面是无参数函数调用,没有形参,下面是加入形参的函数声明:

foo(x, y) =>
   return x + y

ret = foo 1,5

MoonScript的函数调用,可以不使用(),省着去括号。

接下来,用类封装函数和成员表量,用一个单根继承两类做说明。

class CandyLab 
    @metadata: "Candy Lab"

class Candy extends CandyLab

    @name: "Candy"
    
    @value: "From CandyLab"
    
    @func1: =>
        print @name
        print @value + 6
        print "func1"

    @func2: (x, y) =>
        print x + y
        return x + y

    @func3: =>
        print "ok"
        print "#{@metadata}"

MoonScirpt的对象变量和函数可能直接在外部调用:

Candy\func1!
ret = Candy\func2 1,5 
Candy\func3!

在Candy类中的func3,直接引用的父类的变量metadata,另一个比较独特的地方是,用!表 示调用无参函数。MoonScript的类继承关键还是与Java接近extends。

下面是没有继承关系的两个类之间的函数调用与变量引用,而在引用的过程中有一个特别 一点的表量类型声明,就是Table类型。

class CandyLab 
    endpoints: 1
    tbl_url: {
             url_1:"http://host.com/1",
             url_2:"http://host.com/2",
             url_3:"http://host.com/3"
         }
          
class Candy
    @func1: =>
        print(Common.endpoints)  
        print(type(Common.tbl_url["ur1_1"]))

上面的操作是直接在Candy类中调用CandyLab的变量,其实就是没有权限访问。MoonScript 的OO特性比较常用如上,MoonScript这些特性,如果用来做Web开发,效率相对Lua来说还是 高的,而目前用MoonScript实现的最大的一个项目就是Lua框架Lapis,接下来可以看看Lapis 中是如何使用MoonScript的特性的。

作者:糖果

PS:转载到其它平台请注明作者姓名及原文链接,请勿用于商业用途。

https://www.candylab.net

作者编辑:糖果

找了些资料,用了一下docker的openrsty的测试。


直接拉取1.9版的Openresty。

```
docker pull openresty/openresty:1.9.15.1-trusty
```


将特理机的8080端口和docker的80端口映射。
将不当前config/nginx.conf映射到docker的usr/local/openresty/nginx/conf/nginx.conf,log文件同理。

```
#!/usr/bin/env bash
docker run -d --name="nginx" -p 8080:80 -v $PWD/config/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro -v $PWD/logs:/usr/local/openresty/nginx/logs openresty/openresty:1.9.15.1-trusty
```

写一句支持nginx lua的测试脚本。
```
worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {
    server {
        listen 80;
        location / {
            default_type text/html;
            content_by_lua '
                ngx.say("<p>hello, world</p>")
            ';
        }
    }
}
```


停止docker,可以stop,也可以kill。
```
#!/usr/bin/env bash
docker kill nginx && docker rm nginx
```

登陆docker hub
```
docker login
```

提交一个版本
```
docker commit xxxxxxx  candylab/openrestytest
```

提交文件到hub上
```
docker push candylab/openrestytest
```



还有一个--net选项, --net=host,是直接桥接网卡。
docker run -d --net=host openresty

稀疏数组

# 稀疏数组

请看示例代码(注意data的数组下标):

```lua
-- http://www.kyne.com.au/~mark/software/lua-cjson.php
-- version: 2.1 devel

local json = require("cjson")

local data = {1, 2}
data[1000] = 99

-- ... do the other things
ngx.say(json.encode(data))
```

运行日志报错结果:

```
2015/06/27 00:23:13 [error] 2714#0: *40 lua entry thread aborted: runtime error: ...ork/git/github.com/lua-resty-memcached-server/t/test.lua:13: Cannot serialise table: excessively sparse array
stack traceback:
coroutine 0:
[C]: in function 'encode'
...ork/git/github.com/lua-resty-memcached-server/t/test.lua:13: in function <...ork/git/github.com/lua-resty-memcached-server/t/test.lua:1>, client: 127.0.0.1, server: localhost, request: "GET /test HTTP/1.1", host: "127.0.0.1:8001"
```

如果把data的数组下标修改成5,那么这个json.encode就会是成功的。
结果是:[1,2,null,null,99]

为什么下标是1000就失败呢?实际上这么做是cjson想保护你的内存资源。她担心这个下标过大直接撑爆内存(贴心小棉袄啊)。如果我们一定要让这种情况下可以encode,就要尝试encode_sparse_array api了。有兴趣的同学可以自己试一试。我相信你看过有关cjson的代码后,就知道cjson的一个简单危险防范应该是怎样完成的。