上回书,我们说到飞天玉虎蒋伯芳来到蜈蚣岭,不是,重来,上回咱们说到可以在Erlang Shell里面手工构造,加载并调用一个模块.在那个demo里面,我把多个Form单独生成出来,最后放在一起做compile:forms,是不是可以简单点?我们先看完整的module代码,erl_scan:string之后是什么样子的:
 

erl_syntax

 
Eshell V5.10.2  (abort with ^G)
1> Code = "-module(t).\n-export([say/0]).\n\nsay() -> \"Hello world!!\". ".
"-module(t).\n-export([say/0]).\n\nsay() -> \"Hello world!!\". "
2> {ok,Tokens,_} =erl_scan:string(Code).
{ok,[{'-',1},
{atom,1,module},
{'(',1},
{atom,1,t},
{')',1},
{dot,1},
{'-',2},
{atom,2,export},
{'(',2},
{'[',2},
{atom,2,say},
{'/',2},
{integer,2,0},
{']',2},
{')',2},
{dot,2},
{atom,4,say},
{'(',4},
{')',4},
{'->',4},
{string,4,"Hello world!!"},
{dot,4}],
4}

  

 
 可以看到上面的list里面包含了若干Form,erl_scan可以逐行解析代码:
4> erl_scan:tokens([],Code,1).
{done,{ok,[{'-',1},
{atom,1,module},
{'(',1},
{atom,1,t},
{')',1},
{dot,1}],
2},
"-export([say/0]).\n\nsay() -> \"Hello world!!\". "}

  

 
当然还有更简单的方式,dynamic_compile 项目把这些事情都做了,还考虑了更为复杂的情况,比如头文件,宏,注释,record之类的, https://github.com/JacobVorreuter/dynamic_compile/blob/master/src/dynamic_compile.erl 下面就是dynamic_compile使用的一个例子: 
 
Eshell V5.10.2  (abort with ^G)
1> Code = "-module(t).\n-export([say/0]).\n\nsay() -> \"Hello world!!\". ".
"-module(t).\n-export([say/0]).\n\nsay() -> \"Hello world!!\". "
2> dynamic_compile:load_from_string(Code).
{module,t}
3> t:say().
"Hello world!!"
4>

  

 
上面拼字符串的方法看起来丑?你可以选择erl_syntax,下面我们用比较"优雅"的方法去创建t模块:

Eshell V5.10.2  (abort with ^G)
1> M = erl_syntax:attribute(erl_syntax:atom(module),[erl_syntax:atom(t)]).
{tree,attribute,
{attr,0,[],none},
{attribute,{tree,atom,{attr,0,[],none},module},
[{tree,atom,{attr,0,[],none},t}]}}
2> MF = erl_syntax:revert(M).
{attribute,0,module,t}
3> E = erl_syntax:attribute(erl_syntax:atom(export),[erl_syntax:list([erl_syntax:arity_qualifier(erl_syntax:atom(say),erl_syntax:integer(0))])]).
{tree,attribute,
{attr,0,[],none},
{attribute,
{tree,atom,{attr,0,[],none},export},
[{tree,list,
{attr,0,[],none},
{list,
[{tree,arity_qualifier,
{attr,0,[],none},
{arity_qualifier,
{tree,atom,{attr,0,[],none},say},
{tree,integer,{attr,0,[],none},0}}}],
none}}]}}
4> ExportForm = erl_syntax:revert(E).
{attribute,0,export,[{say,0}]}
5>
5>
5> Clause= erl_syntax:clause([],[],[erl_syntax:atom(hello_world)]).
{tree,clause,
{attr,0,[],none},
{clause,[],none,[{tree,atom,{attr,0,[],none},hello_world}]}}
6>
6> Function = erl_syntax:function(erl_syntax:atom(say),[Clause]).
{tree,function,
{attr,0,[],none},
{func,{tree,atom,{attr,0,[],none},say},
[{tree,clause,
{attr,0,[],none},
{clause,[],none,
[{tree,atom,{attr,0,[],none},hello_world}]}}]}}
7> FunctionForm = erl_syntax:revert(Function).
{function,0,say,0,[{clause,0,[],[],[{atom,0,hello_world}]}]}
8> {ok, Mod, Bin1} = compile:forms([MF,ExportForm, FunctionForm]).
{ok,t,
<<70,79,82,49,0,0,1,208,66,69,65,77,65,116,111,109,0,0,0,
57,0,0,0,6,1,116,...>>}
9> t:say().
** exception error: undefined function t:say/0
10> code:load_binary(Mod, [], Bin1).
{module,t}
11> t:say().
hello_world
12>

  

 
 Erlang Shared Data using mochiglobal里面mochiglobal 就是用这种方法实现的,不过,不过,又会有人提意见了,这编写难度也太大了,能折中一下吗?好吧,请出下一位嘉宾smerl
 
 
   我曾经介绍过开源项目smerl,其定位就是Simple Metaprogramming for Erlang, 我们可以从这份代码里面学到erl_scan erl_parse erl_eval更灵活的应用,项目地址:http://code.google.com/p/smerl/ 
 
test_smerl() ->
M1 = smerl:new(foo),
{ok, M2} = smerl:add_func(M1, "bar() -> 1 + 1."),
smerl:compile(M2),
foo:bar(), % returns 2``
smerl:has_func(M2, bar, 0). % returns true

  

 

parse_transform

 
  在上篇文章里面,我需要反复生成 Abstract Format,开始手工搞了一下,后来不胜其烦就使用了一下parse_transform.这东西是干什么用的呢?
 
{parse_transform,Module}
Causes the parse transformation function Module:parse_transform/2 to be applied to the parsed code before the code is checked for errors.
 
 对,它就是允许你在检查错误之前插入自己的逻辑,把那些"奇怪的东西"变成正常的东西,当然你可以选择什么都不做,仅仅打印,看代码:
 
-module(print_form).
-export([parse_transform/2]). parse_transform(Forms, _Options) ->
io:format("forms: ~p~n", [Forms]),
Forms.

  

 
下面,我们写一个简单的模块a.erl,然后编译它,看输出:
 
[root@nimbus demo]# cat a.erl
-module(a).
-compile({parse_transform,print_form}).
-export([test/0]). test()->
"hello world!". [root@nimbus demo]# erlc -o . -pa . a.erl
forms: [{attribute,1,file,{"a.erl",1}},
{attribute,1,module,a},
{attribute,3,export,[{test,0}]},
{function,5,test,0,[{clause,5,[],[],[{string,6,"hello world!"}]}]},
{eof,10}]

  

好吧,感冒,鼻子堵得难受,先到这里吧
 
 
 
参考资料:
 
 
[1] Erlang: How to Create and Compile Module in Run-time
 
 
 
最后小图一张,最早在山东卫视凌晨剧场看过第一季,现在已经14季了, 老员工只有Nicky ,Sara ,Jim了:
 
 

[Erlang 0111] Erlang Abstract Format , Part 2的更多相关文章

  1. [Erlang 0110] Erlang Abstract Format , Part 1

    Erlang Abstract Format并不难懂,只是枯燥一点罢了,如果把Abstract Format的文档翻译出来,其实就是Erlang教科书中语法入门的部分. Erlang Abstract ...

  2. [Erlang 0129] Erlang 杂记 VI

    把之前阅读资料的时候记下的东西,整理了一下. Adding special-purpose processor support to the Erlang VM   P23 简单介绍了Erlang C ...

  3. [Erlang 0124] Erlang Unicode 两三事 - 补遗

    最近看了Erlang User Conference 2013上patrik分享的BRING UNICODE TO ERLANG!视频,这个分享很好的梳理了Erlang Unicode相关的问题,基本 ...

  4. [Erlang 0105] Erlang Resources 小站 2013年1月~6月资讯合集

    很多事情要做,一件一件来; Erlang Resources 小站 2013年1月~6月资讯合集,方便检索.      小站地址: http://site.douban.com/204209/     ...

  5. [Erlang 0122] Erlang Resources 2014年1月~6月资讯合集

    虽然忙,有些事还是要抽时间做; Erlang Resources 小站 2014年1月~6月资讯合集,方便检索.      小站地址: http://site.douban.com/204209/   ...

  6. Erlang 103 Erlang分布式编程

    Outline 笔记系列 Erlang环境和顺序编程Erlang并发编程Erlang分布式编程YawsErlang/OTP 日期              变更说明 2014-11-23 A Outl ...

  7. [Erlang 0057] Erlang 排错利器: Erlang Crash Dump Viewer

    http://www.cnblogs.com/me-sa/archive/2012/04/28/2475556.html Erlang Crash Dump Viewer真的是排错的天兵神器,还记得我 ...

  8. [Erlang 0118] Erlang 杂记 V

       我在知乎回答问题不多,这个问题: "对你职业生涯帮助最大的习惯是什么?它是如何帮助你的?",我还是主动回答了一下.    做笔记 一开始笔记软件做的不好的时候就发邮件给自己, ...

  9. [Erlang 0107] Erlang实现文本截断

       抽时间处理一下之前积压的一些笔记.前段时间有网友 @稻草人 问字符串截断的问题"各位大侠 erlang截取字符串一般用哪个函数啊",有人支招用string:substr/3, ...

随机推荐

  1. 利用AOP写2PC框架(一)

    并不是很想写这个系列,因为这个2pc单独写一个小架构有点鸡肋.不过也不知道写什么了,先写了再说吧. 整个流程如下图: 关于AOP系列的文章很多,我这里也再重复造一下轮子. 首先,我们定义了一个IAop ...

  2. Eclipse常用设置

    用惯了VS,再回过去用Eclipse真是一件痛苦的事.so,在这里记录下使用过程中的一些设置以做备忘. 1.代码自动提示 在我们忘记方法名或者想偷懒时,代码自动提示很管用.不过Eclipse默认是输入 ...

  3. 如何扩展 Visual Studio 编辑器

    在 Visual Studio 2010 的时代,扩展 Visual Studio 的途径有很多,开发者可以选择宏.Add-in.MEF 和 VSPackages 进行自定义的扩展.但是宏在 Visu ...

  4. jquery库和cityselect插 件的省市 级联

    /*$(function(){ $("#select_provice").citySelect({ prov:"北京", nodata:"none&q ...

  5. Java——搭建自己的RESTful API服务器(SpringBoot、Groovy)

    这又是一篇JavaWeb相关的博客,内容涉及: SpringBoot:微框架,提供快速构建服务的功能 SpringMVC:Struts的替代者 MyBatis:数据库操作库 Groovy:能与Java ...

  6. 5.如何使主机和虚拟机IP处于同一网段(内网渗透专用)

    先说一下正常流程: 1.打开虚拟机网络设置选项,选择桥接模式(Bridged)[如果是Kali 2.0的话,执行第一步后就OK了(90%)] 2.打开Kali里面的网络设置 3.设置一个ip4或者ip ...

  7. 了解HTML列表

    前面的话 从某种意义上讲,不是描述性文本的任何内容都可以认为是列表.人口普查.太阳系.餐馆菜单等都可以表示为一个列表或列表的列表.列表分为无序列表.有序列表和定义列表三种 无序列表 无序列表(unor ...

  8. 结合阿里云服务器,使用FTP上传和下载文件,出现的问题和解决方案

    一.FTP出现的问题 二.在网上找的方案 如果使用FileZilla默认设置连接ftp服务器的话可能会报以下错误: 错误: 无法建立数据连接:ECONNREFUSED - Connection ref ...

  9. 排版紧凑情况下IOS 浏览器的文字部分选中问题

    一.需求 一个每一项都是图文混排的列表页,在需要对其中的某一部分文字进行选中copy的时候,IOS个二货每次都是直接选中了整个列表项,无论怎么操作它的选框都没有办法做到部分选中. 这是我本周遇到遇到的 ...

  10. Spring Bean的生命周期(非常详细)

    Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...