国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > PHP > 正文

Perl6 的 YAML::Dumper 模塊使用詳解

2024-05-04 21:49:28
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

這兩天決定試一把 Perl6,因?yàn)榉鰟P兄已經(jīng)把還沒(méi)有正式發(fā)行 Rakudo Star 包的 MoarVM 編譯打包好了,所以可以跳過(guò)這步直接進(jìn)入模塊安裝。當(dāng)然,源碼編譯本身也沒(méi)有太大難度,只不過(guò)從 github 下源碼本身耗時(shí)間比較久而已。

既然木有 Star 包,那么安裝好 MoarVM 上的 Rakudo 后我們就有必要先自己把 panda 之類(lèi)的工具編譯出來(lái)。這一步需要注意一下你的 @*INC 路徑和實(shí)際的 $PERL6LIB 路徑,已經(jīng)編譯之后的 panda 存在的 $PATH 是不是都正確,如果不對(duì)的修改一下 ~/.bashrc 就好了。

我的嘗試遷移對(duì)象是一個(gè)很簡(jiǎn)單的 Puppet 的 ENC 腳本,只涉及 SQLite 的讀取,以及 YAML 格式的輸出。通過(guò) panda install DBIish 命令即可安裝好 DBIish 模塊。

腳本本身修改起來(lái)難度不大,結(jié)果如下:

  1. #!/usr/bin/env perl6 
  2. use v6; 
  3. use DBIish; 
  4. use YAML; 
  5. my $base_dir = "/etc/puppet/webui"; 
  6. # 函數(shù)在 Perl6 中依然使用 sub 關(guān)鍵字定義,不過(guò)有個(gè)超酷的特性是 multi sub 
  7. # 腳本中沒(méi)有用到,但是在 YAML::Dumper 中遍地都是,這里也提一句。 
  8. # MAIN 函數(shù)在 Perl6 里可以直接用 :$opt 命令參數(shù)起 getopt 的作用 
  9. # 不過(guò) ENC 腳本就是直接傳一個(gè)主機(jī)名,用不上這個(gè)超酷的特性 
  10. sub MAIN($node) { 
  11. # connect 方法接收參數(shù)選項(xiàng)是 |%opts,所以可以把哈希直接平鋪寫(xiě) 
  12. # 這個(gè) | 的用法一個(gè)月前在《Using Perl6》里看到過(guò) 
  13.     my $dbh = DBIish.connect( 'SQLite', database => "{$base_dir}/node_info.db" ); 
  14.     my $sth = $dbh.prepare("select * from node_info where node_fqdn = ?"); 
  15.     $sth.execute("$node"); 
  16.     my $ret = $sth.fetchrow_hashref; 
  17.     my $res; 
  18.     if ( !$ret ) { 
  19.         $res = { 
  20. # Perl5 的 qw() 在 Perl6 里直接寫(xiě)成 <> 。也不用再通過(guò) [] 來(lái)指明是引用 
  21.             classes     => <puppetd repos>, 
  22.             environment => 'testing', 
  23.         }; 
  24.     } 
  25.     else { 
  26.         $res = { 
  27.             environment => $ret{'environment'}, 
  28.             parameters  => { role => $ret{'role'} }, 
  29.             classes     => {}, 
  30.         }; 
  31. # 這個(gè) for 的用法,在 Perl5 的 Text::Xslate 模板里就用過(guò) 
  32.         for split(',', $ret{'classes'}) -> $class { 
  33.             if ( $class eq 'nginx' ) { 
  34. # 這個(gè) <== 符號(hào)指明數(shù)據(jù)流方向,完全可以把數(shù)組倒過(guò)來(lái),然后用 ==> 寫(xiě)這行 
  35. # 如果不習(xí)慣這種流向操作符的,可以用,號(hào),反正不能跟 Perl5 那樣啥都不寫(xiě) 
  36. # 這里比較怪的一點(diǎn)是我試圖把這么長(zhǎng)的一句分成多行寫(xiě),包括每行后面加,我看到 YAML 代碼里就用分行了,但是我這就會(huì)報(bào)錯(cuò) 
  37. # Perl6 的正則變化較大,這里 /^#/ 要寫(xiě)成 /^'#'/ 或者 /^x23/ 
  38. # 正則 // 前面不加 m// 不會(huì)立刻開(kāi)始匹配 
  39. # 原先的 s///g 可以寫(xiě)作 s:g///,也可以寫(xiě)作對(duì)象式的 .subst(m//, '', :g),. 前面為空就是默認(rèn)的 $_ 
  40. # 捕獲的數(shù)據(jù)存在 @() 數(shù)組里,也可以用 $/[i] 的形式獲取 
  41. # 字符串內(nèi)插時(shí),不再寫(xiě)作 ${*},而是 {$*} 的形式 
  42. # 命名捕獲這里沒(méi)用上,寫(xiě)個(gè)示例: 
  43. #     $str ~~ /^(w+?)$<laststr>=(w ** 4)w$/; 
  44. #     $/<laststr>.chomp.say; 
  45. # 注意里面的 w{4} 變成了 w ** 4 
  46.                 my @needs <== map { .subst(m/^(.+):(d+)$/, "{$/[0]} max_fails=30 weight={$/[1]}", :g) } <== grep { !m/^x23/ } <== split(',', $ret{'extstr'}); 
  47.                 $res{'classes'}{'nginx'}{'iplist'} = @needs; 
  48.             } 
  49.             else { 
  50. # Perl5 的 undef 不再使用,可以使用 Nil 或者 Any 對(duì)象 
  51.                 $res{'classes'}{$class} = Nil; 
  52.             } 
  53.         } 
  54.     }; 
  55.     $dbh.disconnect(); 
  56. # 這個(gè) dump 就是 YAML 模塊導(dǎo)出的函數(shù) 
  57. # Perl6 的模塊要導(dǎo)出函數(shù)不再需要 Exporter 那樣,直接用 our sub dump($obj) {} 就可以了 
  58.     say dump($res); 
  59. }; 

但是麻煩的是 YAML 模塊本身,這個(gè)模塊是 ingydotnet 在好幾年前草就,后來(lái)就沒(méi)管了,實(shí)際現(xiàn)在壓根跑不起來(lái),花了半天時(shí)間,一邊學(xué)習(xí)一邊修改,總算修改正常了,主要涉及了 Attribute 對(duì)象,Nil 對(duì)象,twigls 前綴符,:exists 定義幾個(gè)概念,以及 YAML 格式本身的處理邏輯.

YAML模塊修改對(duì)比如下:

  1. diff --git a/lib/YAML/Dumper.pm b/lib/YAML/Dumper.pm 
  2. index d7a7981..ec47341 100644 
  3. --- a/lib/YAML/Dumper.pm 
  4. +++ b/lib/YAML/Dumper.pm 
  5. @@ -2,16 +2,16 @@ use v6; 
  6.  class YAML::Dumper; 
  7.  has $.out = []; 
  8. -has $.seen is rw = {}; 
  9. +has $.seen = {}; 
  10.  has $.tags = {}; 
  11.  has $.anchors = {}; 
  12.  has $.level is rw = 0; 
  13. -has $.id is rw = 1; 
  14. +has $.id = 1; 
  15.  has $.info = []; 
  16.  method dump($object) { 
  17.      $.prewalk($object); 
  18. -    $.seen = {}; 
  19. +    $!seen = {}; 
  20.      $.dump_document($object); 
  21.      return $.out.join(''); 
  22.  } 
  23. @@ -45,11 +45,11 @@ method dump_collection($node$kind$function) { 
  24.  method check_special($node) { 
  25.      my $first = 1; 
  26. -    if $.anchors.exists($node.WHICH) { 
  27. -    if $.anchors.exists($node.WHICH) { 
  28. +    if $.anchors{$node.WHICH}:exists { 
  29.          push $.out, ' ''&' ~ $.anchors{$node.WHICH}; 
  30.          $first = 0; 
  31.      } 
  32. -    if $.tags.exists($node.WHICH) { 
  33. +    if $.tags{$node.WHICH}:exists { 
  34.          push $.out, ' ''!' ~ $.tags{$node.WHICH}; 
  35.          $first = 0; 
  36.      } 
  37. @@ -64,7 +64,7 @@ method indent($first) { 
  38.              return
  39.          } 
  40.          if $.info[*-1]<kind> eq 'seq' && $.info[*-2]<kind> eq 'map' { 
  41. -            $seq_in_map = 1; 
  42. +            $seq_in_map = 0; 
  43.          } 
  44.      } 
  45.      push $.out, "n"
  46. @@ -155,7 +155,8 @@ method dump_object($node$type) { 
  47.      $.tags{$repr.WHICH} = $type
  48.      for $node.^attributes -> $a { 
  49.          my $name = $a.name.substr(2); 
  50. -        my $value = pir::getattribute__PPs($node$a.name);     #RAKUDO 
  51. +        #my $value = pir::getattribute__PPs($node$a.name);     #RAKUDO 
  52. +        my $value = $a.get_value($node);                         #for non-parrot 
  53.          $repr{$name} = $value
  54.      }//開(kāi)源軟件:Vevb.com 
  55.      $.dump_node($repr); 

這里的 $.seen 和 $!seen 是不是暈掉了?其實(shí) $.seen 就相當(dāng)于先聲明了 $!seen 后再自動(dòng)創(chuàng)建一個(gè) method seen() { return $!seen }。

另一處是 pir::getattribute__PPs() 函數(shù),pir 是 parrot 上的語(yǔ)言,而 MoarVM 和 JVM 上都是先實(shí)現(xiàn)了一個(gè) nqp 再用 nqp 寫(xiě) Perl6,不巧的是這個(gè) pir 里的 getattribute__PPs() 剛好至今還沒(méi)有對(duì)應(yīng)的 nqp 方法。(在 pir2nqp.todo 文件里可見(jiàn))

所以只能用高級(jí)的 Perl6 語(yǔ)言來(lái)做了。

總的來(lái)說(shuō),這個(gè) yaml-pm6 代碼里很多地方都是試來(lái)試去,同樣的效果不同的寫(xiě)法,又比如 .WHICH 和 .WHAT.perl 也是混用。 而且我隨手測(cè)試了一下,即使在 parrot 上,用 pir::getattribute__PPs 的速度也比 Attribute.get_value 還差點(diǎn)點(diǎn)。

最后提一句,目前 ENC 腳本在 perl5、perl6-m、perl6-p、perl6-j 上的運(yùn)行時(shí)間大概分別是 0.13、1.5、2.8、12s。MoarVM 還差 Perl5 十倍,領(lǐng)先 parrot 一倍。不過(guò) JVM 本身啟動(dòng)時(shí)間很長(zhǎng),這里不好因?yàn)橐粋€(gè)短時(shí)間腳本說(shuō)它太慢。

另外還試了一下如果把我修改過(guò)的 YAML::Dumper 類(lèi)直接寫(xiě)在腳本里運(yùn)行,也就是不編譯成 moarvm 模塊,時(shí)間大概是 2.5s,比 parrot 模塊還快點(diǎn)點(diǎn)。

不過(guò)如何把 perl6 腳本本身編譯成 moarvm 的 bytecode 格式運(yùn)行還沒(méi)有研究出來(lái),直接 perl6-m --target=mbc --output=name.moarvm name.pl6 得到的文件運(yùn)行 moar name.moarvm 的結(jié)果運(yùn)行會(huì)內(nèi)存報(bào)錯(cuò)。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 贵州省| 屏东市| 莒南县| 平昌县| 额敏县| 江西省| 福海县| 鹤岗市| 桂林市| 永春县| 内江市| 高雄市| 布拖县| 察隅县| 常山县| 合肥市| 通许县| 江西省| 洪泽县| 高淳县| 阳原县| 卓尼县| 南投县| 晋宁县| 晋江市| 崇左市| 泰顺县| 黑山县| 凤冈县| 襄城县| 海晏县| 黑山县| SHOW| 平果县| 旌德县| 红河县| 嘉鱼县| 红安县| 汤阴县| 太原市| 石渠县|