热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Perl6的YAML::Dumper模块使用详解

这两天决定试一把Perl6,因为扶凯兄已经把还没有正式发行RakudoStar包的MoarVM编译打包好了,所以可以跳过这步直接进入模块安装。当然,源码编译本身也没有太大难度,只不过...
这两天决定试一把 Perl6,因为扶凯兄已经把还没有正式发行 Rakudo Star 包的 MoarVM 编译打包好了,所以可以跳过这步直接进入模块安装。当然,源码编译本身也没有太大难度,只不过从 github 下源码本身耗时间比较久而已。

既然木有 Star 包,那么安装好 MoarVM 上的 Rakudo 后我们就有必要先自己把 panda 之类的工具编译出来。这一步需要注意一下你的 @*INC 路径和实际的 $PERL6LIB 路径,已经编译之后的 panda 存在的 $PATH 是不是都正确,如果不对的修改一下 ~/.bashrc 就好了。

我的尝试迁移对象是一个很简单的 Puppet 的 ENC 脚本,只涉及 SQLite 的读取,以及 YAML 格式的输出。通过 panda install DBIish 命令即可安装好 DBIish 模块。

脚本本身修改起来难度不大,结果如下:

#!/usr/bin/env perl6 
use v6; 
use DBIish; 
use YAML; 
my $base_dir = "/etc/puppet/webui"; 
# 函数在 Perl6 中依然使用 sub 关键字定义,不过有个超酷的特性是 multi sub 
# 脚本中没有用到,但是在 YAML::Dumper 中遍地都是,这里也提一句。 
# MAIN 函数在 Perl6 里可以直接用 :$opt 命令参数起 getopt 的作用 
# 不过 ENC 脚本就是直接传一个主机名,用不上这个超酷的特性 
sub MAIN($node) { 
# connect 方法接收参数选项是 |%opts,所以可以把哈希直接平铺写 
# 这个 | 的用法一个月前在《Using Perl6》里看到过 
	my $dbh = DBIish.connect( 'SQLite', database => "{$base_dir}/node_info.db" ); 
	my $sth = $dbh.prepare("select * from node_info where node_fqdn = ?"); 
	$sth.execute("$node"); 
	my $ret = $sth.fetchrow_hashref; 
	my $res; 
	if ( !$ret ) { 
		$res = { 
# Perl5 的 qw() 在 Perl6 里直接写成 <> 。也不用再通过 [] 来指明是引用 
			classes     => , 
			envirOnment=> &#39;testing&#39;, 
		}; 
	} 
	else { 
		$res = { 
			envirOnment=> $ret{&#39;environment&#39;}, 
			parameters  => { role => $ret{&#39;role&#39;} }, 
			classes     => {}, 
		}; 
# 这个 for 的用法,在 Perl5 的 Text::Xslate 模板里就用过 
		for split(&#39;,&#39;, $ret{&#39;classes&#39;}) -> $class { 
			if ( $class eq &#39;nginx&#39; ) { 
# 这个 <== 符号指明数据流方向,完全可以把数组倒过来,然后用 ==> 写这行 
# 如果不习惯这种流向操作符的,可以用,号,反正不能跟 Perl5 那样啥都不写 
# 这里比较怪的一点是我试图把这么长的一句分成多行写,包括每行后面加,我看到 YAML 代码里就用分行了,但是我这就会报错 
# Perl6 的正则变化较大,这里 /^#/ 要写成 /^&#39;#&#39;/ 或者 /^x23/ 
# 正则 // 前面不加 m// 不会立刻开始匹配 
# 原先的 s///g 可以写作 s:g///,也可以写作对象式的 .subst(m//, &#39;&#39;, :g),. 前面为空就是默认的 $_ 
# 捕获的数据存在 @() 数组里,也可以用 $/[i] 的形式获取 
# 字符串内插时,不再写作 ${*},而是 {$*} 的形式 
# 命名捕获这里没用上,写个示例: 
#     $str ~~ /^(w+?)$=(w ** 4)w$/; 
#     $/.chomp.say; 
# 注意里面的 w{4} 变成了 w ** 4 
				my @needs <== map { .subst(m/^(.+):(d+)$/, "{$/[0]} max_fails=30 weight={$/[1]}", :g) } <== grep { !m/^x23/ } <== split(&#39;,&#39;, $ret{&#39;extstr&#39;}); 
				$res{&#39;classes&#39;}{&#39;nginx&#39;}{&#39;iplist&#39;} = @needs; 
			} 
			else { 
# Perl5 的 undef 不再使用,可以使用 Nil 或者 Any 对象 
				$res{&#39;classes&#39;}{$class} = Nil; 
			} 
		} 
	}; 
	$dbh.disconnect(); 
# 这个 dump 就是 YAML 模块导出的函数 
# Perl6 的模块要导出函数不再需要 Exporter 那样,直接用 our sub dump($obj) {} 就可以了 
	say dump($res); 
};

但是麻烦的是 YAML 模块本身,这个模块是 ingydotnet 在好几年前草就,后来就没管了,实际现在压根跑不起来,花了半天时间,一边学习一边修改,总算修改正常了,主要涉及了 Attribute 对象,Nil 对象,twigls 前缀符,:exists 定义几个概念,以及 YAML 格式本身的处理逻辑.

YAML模块修改对比如下:

diff --git a/lib/YAML/Dumper.pm b/lib/YAML/Dumper.pm 
index d7a7981..ec47341 100644 
--- a/lib/YAML/Dumper.pm 
+++ b/lib/YAML/Dumper.pm 
@@ -2,16 +2,16 @@ use v6; 
 class YAML::Dumper; 
 has $.out = []; 
-has $.seen is rw = {}; 
+has $.seen = {}; 
 has $.tags = {}; 
 has $.anchors = {}; 
 has $.level is rw = 0; 
-has $.id is rw = 1; 
+has $.id = 1; 
 has $.info = []; 
 method dump($object) { 
	 $.prewalk($object); 
-    $.seen = {}; 
+    $!seen = {}; 
	 $.dump_document($object); 
	 return $.out.join(&#39;&#39;); 
 } 
@@ -45,11 +45,11 @@ method dump_collection($node, $kind, $function) { 
 method check_special($node) { 
	 my $first = 1; 
-    if $.anchors.exists($node.WHICH) { 
-    if $.anchors.exists($node.WHICH) { 
+    if $.anchors{$node.WHICH}:exists { 
		 push $.out, &#39; &#39;, &#39;&&#39; ~ $.anchors{$node.WHICH}; 
		 $first = 0; 
	 } 
-    if $.tags.exists($node.WHICH) { 
+    if $.tags{$node.WHICH}:exists { 
		 push $.out, &#39; &#39;, &#39;!&#39; ~ $.tags{$node.WHICH}; 
		 $first = 0; 
	 } 
@@ -64,7 +64,7 @@ method indent($first) { 
			 return; 
		 } 
		 if $.info[*-1] eq &#39;seq&#39; && $.info[*-2] eq &#39;map&#39; { 
-            $seq_in_map = 1; 
+            $seq_in_map = 0; 
		 } 
	 } 
	 push $.out, "n"; 
@@ -155,7 +155,8 @@ method dump_object($node, $type) { 
	 $.tags{$repr.WHICH} = $type; 
	 for $node.^attributes -> $a { 
		 my $name = $a.name.substr(2); 
-        my $value = pir::getattribute__PPs($node, $a.name);     #RAKUDO 
+        #my $value = pir::getattribute__PPs($node, $a.name);     #RAKUDO 
+        my $value = $a.get_value($node);                         #for non-parrot 
		 $repr{$name} = $value; 
	 } 
	 $.dump_node($repr);

这里的 $.seen 和 $!seen 是不是晕掉了?其实 $.seen 就相当于先声明了 $!seen 后再自动创建一个 method seen() { return $!seen }。

另一处是 pir::getattribute__PPs() 函数,pir 是 parrot 上的语言,而 MoarVM 和 JVM 上都是先实现了一个 nqp 再用 nqp 写 Perl6,不巧的是这个 pir 里的 getattribute__PPs() 刚好至今还没有对应的 nqp 方法。(在 pir2nqp.todo 文件里可见)

所以只能用高级的 Perl6 语言来做了。

总的来说,这个 yaml-pm6 代码里很多地方都是试来试去,同样的效果不同的写法,又比如 .WHICH 和 .WHAT.perl 也是混用。 而且我随手测试了一下,即使在 parrot 上,用 pir::getattribute__PPs 的速度也比 Attribute.get_value 还差点点。

最后提一句,目前 ENC 脚本在 perl5、perl6-m、perl6-p、perl6-j 上的运行时间大概分别是 0.13、1.5、2.8、12s。MoarVM 还差 Perl5 十倍,领先 parrot 一倍。不过 JVM 本身启动时间很长,这里不好因为一个短时间脚本说它太慢。

另外还试了一下如果把我修改过的 YAML::Dumper 类直接写在脚本里运行,也就是不编译成 moarvm 模块,时间大概是 2.5s,比 parrot 模块还快点点。

不过如何把 perl6 脚本本身编译成 moarvm 的 bytecode 格式运行还没有研究出来,直接 perl6-m --target=mbc --output=name.moarvm name.pl6 得到的文件运行 moar name.moarvm 的结果运行会内存报错。

本文地址:

转载随意,但请附上文章地址:-)

推荐阅读
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 本文介绍了在MacOS系统上安装MySQL的步骤,并详细说明了如何设置MySQL服务的开机启动和如何修改MySQL的密码。通过下载MySQL的macos版本并按照提示一步一步安装,在系统偏好设置中可以找到MySQL的图标进行设置。同时,还介绍了通过终端命令来修改MySQL的密码的具体操作步骤。 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • PHP组合工具以及开发所需的工具
    本文介绍了PHP开发中常用的组合工具和开发所需的工具。对于数据分析软件,包括Excel、hihidata、SPSS、SAS、MARLAB、Eview以及各种BI与报表工具等。同时还介绍了PHP开发所需的PHP MySQL Apache集成环境,包括推荐的AppServ等版本。 ... [详细]
  • Linux下部署Symfoy2对app/cache和app/logs目录的权限设置,symfoy2logs
    php教程|php手册xml文件php教程-php手册Linux下部署Symfoy2对appcache和applogs目录的权限设置,symfoy2logs黑色记事本源码,vsco ... [详细]
  • ZABBIX 3.0 配置监控NGINX性能【OK】
    1.在agent端查看配置:nginx-V查看编辑时是否加入状态监控模块:--with-http_stub_status_module--with-http_gzip_stat ... [详细]
  • Nginx Buffer 机制引发的下载故障
    Nginx ... [详细]
  • 现在比较流行使用静态网站生成器来搭建网站,博客产品着陆页微信转发页面等。但每次都需要对服务器进行配置,也是一个重复但繁琐的工作。使用DockerWeb,只需5分钟就能搭建一个基于D ... [详细]
  • 有意向可以发简历到邮箱内推.简历直达组内Leader.能做同事的话,内推奖励全给你. ... [详细]
  • Imdevelopinganappwhichneedstogetmusicfilebystreamingforplayinglive.我正在开发一个应用程序,需要通过流 ... [详细]
author-avatar
email_osoo_240
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有