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

 更新时间:2016年11月25日 17:37  点击:2268
这两天决定试一把 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     => <puppetd repos>,
            environment => 'testing',
        };
    }
    else {
        $res = {
            environment => $ret{'environment'},
            parameters  => { role => $ret{'role'} },
            classes     => {},
        };
# 这个 for 的用法,在 Perl5 的 Text::Xslate 模板里就用过
        for split(',', $ret{'classes'}) -> $class {
            if ( $class eq 'nginx' ) {
# 这个 <== 符号指明数据流方向,完全可以把数组倒过来,然后用 ==> 写这行
# 如果不习惯这种流向操作符的,可以用,号,反正不能跟 Perl5 那样啥都不写
# 这里比较怪的一点是我试图把这么长的一句分成多行写,包括每行后面加,我看到 YAML 代码里就用分行了,但是我这就会报错
# Perl6 的正则变化较大,这里 /^#/ 要写成 /^'#'/ 或者 /^x23/
# 正则 // 前面不加 m// 不会立刻开始匹配
# 原先的 s///g 可以写作 s:g///,也可以写作对象式的 .subst(m//, '', :g),. 前面为空就是默认的 $_
# 捕获的数据存在 @() 数组里,也可以用 $/[i] 的形式获取
# 字符串内插时,不再写作 ${*},而是 {$*} 的形式
# 命名捕获这里没用上,写个示例:
#     $str ~~ /^(w+?)$<laststr>=(w ** 4)w$/;
#     $/<laststr>.chomp.say;
# 注意里面的 w{4} 变成了 w ** 4
                my @needs <== map { .subst(m/^(.+):(d+)$/, "{$/[0]} max_fails=30 weight={$/[1]}", :g) } <== grep { !m/^x23/ } <== split(',', $ret{'extstr'});
                $res{'classes'}{'nginx'}{'iplist'} = @needs;
            }
            else {
# Perl5 的 undef 不再使用,可以使用 Nil 或者 Any 对象
                $res{'classes'}{$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('');
 }
@@ -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, ' ', '&' ~ $.anchors{$node.WHICH};
         $first = 0;
     }
-    if $.tags.exists($node.WHICH) {
+    if $.tags{$node.WHICH}:exists {
         push $.out, ' ', '!' ~ $.tags{$node.WHICH};
         $first = 0;
     }
@@ -64,7 +64,7 @@ method indent($first) {
             return;
         }
         if $.info[*-1]<kind> eq 'seq' && $.info[*-2]<kind> eq 'map' {
-            $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 的结果运行会内存报错。

原文来自:tiejiang.org

今天忽然发现安装的主机控制面板报这个错误,但是功能还是可以正常使用。网上找了下有两种解决方法,希望下面的方法来给大家带来帮助哦。

看到错误提示如下

Warning: Call-time pass-by-reference has been deprecated in E:网站目录www目录a.php on line 46

Warning: Call-time pass-by-reference has been deprecated in E:网站目录www目录a.php on line 47

Warning: Call-time pass-by-reference has been deprecated in E:网站目录www目录a.php on line 47

Warning: Call-time pass-by-reference has been deprecated in E:网站目录www目录a.php on line 48

Warning: Call-time pass-by-reference has been deprecated in E:网站目录www目录a.php on line 49

Warning: Call-time pass-by-reference has been deprecated in E:网站目录www目录a.php on line 51

Warning: Call-time pass-by-reference has been deprecated in E:网站目录www目录a.php on line 56

Warning: Call-time pass-by-reference has been deprecated in E:网站目录www目录a.php on line 56

解决办法如下:


方法1:

把php.ini的display_errors = on改成display_errors = off // (不显示错误)
就不显示了。
但是这种方法不是太好,只是不显示错误,其实错误还是存在的。

方法2:

1. 在PHP.ini中搜索关键字 : allow_call_time_pass_reference 没有的自行建立。
2. 将 Off 改成 On ,Web Server重起就OK了~
allow_call_time_pass_reference = Off 变成 allow_call_time_pass_reference = On

顺便解释下allow_call_time_pass_reference这个参数的含义:
是否启用在函数调用时强制参数被按照引用传递。此方法已不被赞成并在 PHP/Zend 未来的版本中很可能不再支持。鼓励使用的方法是在函数定义中指定哪些参数应该用引用传递。鼓励大家尝试关闭此选项并确保脚本能够正常运行,以确保该脚本也能在未来的版本中运行(每次使用此特性都会收到一条警告,参数会被按值传递而不是按照引用传递)。

在函数调用时通过引用传递参数是不推荐的,因为它影响到了代码的整洁。如果函数的参数没有声明作为引用传递,函数可以通过未写入文档的方法修改其参数。要避免其副作用,最好仅在函数声明时指定那个参数需要通过引用传递。

今天本来说要测试一个新网站的,结果发现打开之后提示Fatal error: Call to undefined function get_header() in 错误了,下面我就给大家整理此问题解决办法。

效果就成这样了。

Fatal error: Call to undefined function get_header() in /home/wwwfulis/public_html/index.php on line 1;

在wordpress中这个应该算是比较正常的情况,因为基本都是调用模板函数,简单翻译一下就是get_header()这个函数没有定义。

到网 站查询了很多资料都没有显示有效的结果,没办法只好根据他们提供的信息综合分析一下,最后发现这个问题导致的原因有如下的几种,

1.检查这个函数是否是拼写错误 在php里,内置有get_headers() 函数,但是在xammp上面能够调制,为什么在这上面就不能调试了呢。 该函数的功用是:返回一个数组,包含有服务器响应一个 HTTP 请求所发送的标头。如果失败则返回 FALSE 并发出一条 E_WARNING 级别的错误信息

2.检查是否在其它地方定义了这个函数.


如果自己有设置主机php.ini的权限,不操心log的话,可以修改如下,就不会有错误提示了:

 代码如下 复制代码


display_errors = off
error_reporting=E_ALL&~E_NOTICE

因为没有权限懂php.ini,于是,我在index.php中添加不显示运行错误:

 代码如下 复制代码
<?php ini_set('display_errors', 0); ?>

这样以后就没有了错误提示,可是error-log中依旧记录着该错误,如何不记录这个错误呢?如果直接加载index.php且没有定义get_header()这个函数,就直接重定向到网站首页,所以一个简单地判断就可以搞定了。

 

 代码如下 复制代码
<?php ini_set('display_errors', 0); ?>
<?php
/*
 @FileName:index.php
 @Aurthor: OneDou [http://oneodu.com]
 @LastModifed:2013-6-10 下午11:27:33
 @Charset:UTF-8
*/
if (function_exists('get_header')) {
    get_header();
}else{
    header("Location: http://" . $_SERVER['HTTP_HOST'] . "");
    exit;
}; ?>

Ok,这样如果直接访问index.php就被重定向到了首页

在运行一个采集页面时发现超过30秒页面出现Fatal error: Maximum execution time of 30 seconds exceeded in 错误了,这个百度了一下说是配置问题,下面给大家分享解决办法。

报这个错误不是说php执行时间越过了配置文件中设置的最大执行时间30秒钟,不是你的程序错误,而
是系统的配置文件问题,如果你的网速快服务器配置高的话,再执行一次就不会出现这种错误了
有了出现这种问题也可以进行一下修改:
1.修改php的配置文件,找到php.ini文件,它一般应该放在你的C:WINDOWS目录下,然后找到max_execution_time = 30 ;
//设置成你想要的值,单位是秒
这一行,这就是设置的执行时间最大值为30秒,你可以对这个值进行一下修正,改为你的期望值。
2.使用ini_set()函数,不是所有人都能修改php.ini文件的,那么你可以使用这个函数来改变你的最大执行时间限制值,如:
ini_set(‘max_execution_time’, ’100′);
//设置成你想要的值,单位是秒

3:直接在页面加程序

可用程序修改:set_time_limit (0);

在PHP程序开发中,经常会执行字符串的截取操作,比如输出信息列表时,标题不宜过长,打印文章摘要时,也要执行一系列的字符串截取操作。遇到这些需求时,我们经常会想到使用substr()方法来实现,substr()对全英文字符串的截取是比较适合的

但字符串只要出现中文字符,就有可能导致PHP substr中文乱码,因为中文UTF-8编码,每个汉字占3字节,而GB2312占2字节,英文占1字节,截取位数不准确,substr()硬生生地将一个中文字符“锯”成两半,造成断开的字符会把其后的..拉过来一起做一个字,所以出现了PHP substr中文乱码。


substr --- 取得部份字符串

语法 : string substr (string string, int start [, int length])
说明 :
substr( )传回 string的一部份字符串,由参数 start和 length指定。
如果 start是正数,传回的字符串将会从 string的第 start个字元开始。
Example :

 代码如下 复制代码


<?php
$rest = substr ("abcdef", 1); // returns "bcdef"
$rest = substr ("abcdef", 1, 3); // returns "bcd"
?>

如果 start是负数,传回的字符串将会从 string结尾的第 start个字开始。
Example :

 代码如下 复制代码


<?php
$rest = substr ("abcdef", -1); // returns "f"
$rest = substr ("abcdef", -2); // returns "ef"
$rest = substr ("abcdef", -3, 1); // returns "d"
?>

如果有给予参数 length而且是正数时,传回的字符串将会从 start传回 length个字元。
如果有给予参数 length而且是负数时,传回的字符串将会结束于 string结尾的第 length个字元。
Example :

 代码如下 复制代码


<?php
$rest = substr ("abcdef", 1, -1); // returns "bcde"
?>

对于英文没有问题,我们测试一个中文

 代码如下 复制代码

 

<?php
$rest = substr ("中国人", 1, -1); // returns "fdsafsda" 就是乱码了
?>

这种截取字符的结果,肯定不是我们想要的结果,这种出现PHP substr中文乱码的情况,可能会导致程序无法正常运行。解决办法主要有两种:


一、使用mbstring扩展库的mb_substr()截取就不会出现乱码了。

可以用mb_substr()/mb_strcut()这个函数,mb_substr()/mb_strcut()的用法与substr()相似,只是在mb_substr()/mb_strcut最后要加入多一个参数,以设定字符串的编码,但是一般的服务器都没打开php_mbstring.dll,需要在php.ini在把php_mbstring.dll打开。

 代码如下 复制代码

<?php
    echo mb_substr("php中文字符encode",0,4,"utf-8");
?>


如果未指定最后一个编码参数,会是三个字节为一个中文,这就是utf-8编码的特点,若加上utf-8字符集说明,所以,是以一个字为单位来截取的。


使用的时候要注意php文件的编码,和网页显示时的编码。使用这个mb_substr方法要事先知道字符串的编码,如果不知道编码,就需要判断,mbstring库还提供了mb_check_encoding来检验字符串编码,但还不完善。


PHP 自带几种字符串截取函数,其中常用到的就是 substr 和 mb_substr。前者在处理中文时,GBK 为 2 个长度单位,UTF 为 3 个长度单位,后者指定编码后,一个中文即为 1 个长度单位。

substr 有时会截 1/3 个中文或半个中文,会显示乱码,相对来说 mb_substr 更适合我们使用。不过有时候 mb_substr 就显得不那么好用了。例如我要显示一个小图片的简要信息,5 个中文正好,超过 5 个就截取前4再加上 ”…”,这样处理中文是没问题了,可是处理英文或数字,这样截取就太短了。


二、自己书写截取函数,但效率不如用mbstring扩展库来得高。下面是ecshop里面的截取UTF-8编码下字符串的函数。

 代码如下 复制代码

function sub_str($str, $length = 0, $append = true)
{
    $str = trim($str);
    $strlength = strlen($str);
 
    if ($length == 0 || $length >= $strlength)
    {
        return $str;  //截取长度等于0或大于等于本字符串的长度,返回字符串本身
    }
    elseif ($length < 0)  //如果截取长度为负数
    {
        $length = $strlength + $length;//那么截取长度就等于字符串长度减去截取长度
        if ($length < 0)
        {
            $length = $strlength;//如果截取长度的绝对值大于字符串本身长度,则截取长度取字符串本身的长度
        }
    }
 
    if (function_exists('mb_substr'))
    {
        $newstr = mb_substr($str, 0, $length, EC_CHARSET);
    }
    elseif (function_exists('iconv_substr'))
    {
        $newstr = iconv_substr($str, 0, $length, EC_CHARSET);
    }
    else
    {
        //$newstr = trim_right(substr($str, 0, $length));
        $newstr = substr($str, 0, $length);
    }
 
    if ($append && $str != $newstr)
    {
        $newstr .= '...';
    }
 
    return $newstr;
}

[!--infotagslink--]

相关文章

  • 图解PHP使用Zend Guard 6.0加密方法教程

    有时为了网站安全和版权问题,会对自己写的php源码进行加密,在php加密技术上最常用的是zend公司的zend guard 加密软件,现在我们来图文讲解一下。 下面就简单说说如何...2016-11-25
  • ps怎么使用HSL面板

    ps软件是现在很多人都会使用到的,HSL面板在ps软件中又有着非常独特的作用。这次文章就给大家介绍下ps怎么使用HSL面板,还不知道使用方法的下面一起来看看。 &#8195;...2017-07-06
  • Plesk控制面板新手使用手册总结

    许多的朋友对于Plesk控制面板应用不是非常的了解特别是英文版的Plesk控制面板,在这里小编整理了一些关于Plesk控制面板常用的使用方案整理,具体如下。 本文基于Linu...2016-10-10
  • 使用insertAfter()方法在现有元素后添加一个新元素

    复制代码 代码如下: //在现有元素后添加一个新元素 function insertAfter(newElement, targetElement){ var parent = targetElement.parentNode; if (parent.lastChild == targetElement){ parent.appendChild(newEl...2014-05-31
  • jQuery 1.9使用$.support替代$.browser的使用方法

    jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support 。 在更新的 2.0 版本中,将不再支持 IE 6/7/8。 以后,如果用户需要支持 IE 6/7/8,只能使用 jQuery 1.9。 如果要全面支持 IE,并混合...2014-05-31
  • 使用percona-toolkit操作MySQL的实用命令小结

    1.pt-archiver 功能介绍: 将mysql数据库中表的记录归档到另外一个表或者文件 用法介绍: pt-archiver [OPTION...] --source DSN --where WHERE 这个工具只是归档旧的数据,不会对线上数据的OLTP查询造成太大影响,你可以将...2015-11-24
  • 使用GruntJS构建Web程序之构建篇

    大概有如下步骤 新建项目Bejs 新建文件package.json 新建文件Gruntfile.js 命令行执行grunt任务 一、新建项目Bejs源码放在src下,该目录有两个js文件,selector.js和ajax.js。编译后代码放在dest,这个grunt会...2014-06-07
  • 如何使用php脚本给html中引用的js和css路径打上版本号

    在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css、js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候,浏览器就可以从浏览器的缓存中获取css、...2015-11-24
  • C#注释的一些使用方法浅谈

    C#注释的一些使用方法浅谈,需要的朋友可以参考一下...2020-06-25
  • MySQL日志分析软件mysqlsla的安装和使用教程

    一、下载 mysqlsla [root@localhost tmp]# wget http://hackmysql.com/scripts/mysqlsla-2.03.tar.gz--19:45:45-- http://hackmysql.com/scripts/mysqlsla-2.03.tar.gzResolving hackmysql.com... 64.13.232.157Conn...2015-11-24
  • 安装和使用percona-toolkit来辅助操作MySQL的基本教程

    一、percona-toolkit简介 percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦的mysql和系统任务,这些任务包括: 检查master和slave数据的一致性 有效地对记录进行归档 查找重复的索...2015-11-24
  • php语言中使用json的技巧及json的实现代码详解

    目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它。我写过一篇《数据类型和JSON格式》,探讨它的设计思想。今天,我想总结一下PHP语言对它的支持,这是开发互联网应用程序(特别是编写API)必须了解的知识...2015-10-30
  • 使用jquery修改表单的提交地址基本思路

    基本思路: 通过使用jquery选择器得到对应表单的jquery对象,然后使用attr方法修改对应的action 示例程序一: 默认情况下,该表单会提交到page_one.html 点击button之后,表单的提交地址就会修改为page_two.html 复制...2014-06-07
  • PHP实现无限级分类(不使用递归)

    无限级分类在开发中经常使用,例如:部门结构、文章分类。无限级分类的难点在于“输出”和“查询”,例如 将文章分类输出为<ul>列表形式; 查找分类A下面所有分类包含的文章。1.实现原理 几种常见的实现方法,各有利弊。其中...2015-10-23
  • php类的使用实例教程

    php类的使用实例教程 <?php /** * Class program for yinghua05-2 * designer :songsong */ class Template { var $tpl_vars; var $tpl_path; var $_deb...2016-11-25
  • 双冒号 ::在PHP中的使用情况

    前几天在百度知道里面看到有人问PHP中双冒号::的用法,当时给他的回答比较简洁因为手机打字不大方便!今天突然想起来,所以在这里总结一下我遇到的双冒号::在PHP中使用的情况!双冒号操作符即作用域限定操作符Scope Resoluti...2015-11-08
  • 浅析Promise的介绍及基本用法

    Promise是异步编程的一种解决方案,在ES6中Promise被列为了正式规范,统一了用法,原生提供了Promise对象。接下来通过本文给大家介绍Promise的介绍及基本用法,感兴趣的朋友一起看看吧...2021-10-21
  • PHP mysql与mysqli事务使用说明 分享

    mysqli封装了诸如事务等一些高级操作,同时封装了DB操作过程中的很多可用的方法。应用比较多的地方是 mysqli的事务。...2013-10-02
  • Postman安装与使用详细教程 附postman离线安装包

    这篇文章主要介绍了Postman安装与使用详细教程 附postman离线安装包,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-05
  • Python运行提示缺少模块问题解决方案

    这篇文章主要介绍了Python运行提示缺少模块问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-05-10