Posterous theme by Cory Watilo

Open Perl Modules in Vim

在写程序的时候,用到一些perl模块时,经常需要查看这些模块的源代码。以前用的方法是新开一个screen窗口,module_info Module::Name获得模块的路径,然后再在vim里面打开之

久之感觉这样做颇没效率,于是决定写一个vim的函数来实现":Pme Module::Name"即可打开perl模块的功能。

将以下代码写入 .vimrc即可实现这个功能

function! OpenPerlModule(module)
    let module_path = system("perldoc -l " . a:module)
    if v:shell_error == 1
        echo module_path
        return
    endif
    execute "e " . module_path
endfunction
command -nargs=1 Pme call OpenPerlModule(<f-args>)

HTML::FormHandler介绍

根据Catalyst的胖Model,瘦Controller原则,在controller里面应该使用最少的代码来保持整个逻辑的清爽。但对于任何一个web app来说,最复杂的逻辑之一就是表单的提交,验证表单,之后再根据需要从做相关的操作,查询数据库或者返回错误。而这些都是Controller的任务

如果在Controller里面hardcode这部分逻辑,整个代码会变得冗长而丑陋,HTML::FormHandler就是为了简化表单的处理而编写的模块。HTML::FormHandler使用Moose作为底层的OO库,代码实现比较优雅和干净。

一个典型的表单定义如下:

HTML::FormHandler主要分为这么几个部分

  • HTML::FormHandler::Field::*

Field主要用来定义表单单元的类型,对某一种类型,会有相应的验证方法和属性,比如定义一个Text类型单元

has_field 'name'  => (Type => 'Text', maxlength => 30, minlength =>6);
  • HTML::FormHandler::Widget::*

Widget用来生成Field的HTML代码,查看源代码,每一个widget都有个render方法,用来创建wdiget的HTML code,这里有两个特殊的widget。HTML::FormHandler::Widget::Wrapper::*用来添加包裹每个表单单元的HTML, 比如添加的是div还是table.还有一个是Widget::Form,定义

…..
部分如何生成

  • HTML::FormHandler:Moose

使用Moose定义的语法糖,比如has_field

  • HTML::FormHandler::Model::*

与数据库交互的模块,值得注意的是FormHandler没有添加任何数据库操作的代码,而只是使用Moose Role定义了数据库操作所需要的方法。

to be continued…

The reason I won't even use HTML::FormFu and HTML::FormHandler

I built a Catalyst based web application some days ago, and because it was my first Catalyst application, I built it from scratch, I used few high level Plugins, I wrote the web logic all in the Controller, especially “Form-handler' logic.

And then I read some Catalyst document, realized Controller should be thin and I have a lot of plugins available which can make my code clean. So I’d like to pick one to Handler my forms.

First, I have all those Forms already defined in my templates, so I don’t need a module that will generate form for me, also I think let the module generate a form for you automatically is not very good idea. Form is the kind of thing which needs customization, a lot of customization. This eliminate HTML::FormFu, from whose documentation, I can not found a way to reuse my templates.

HTML::FromHandler looks better,I can quickly find the information it is possible to reuse my template from the document, but still it’s not perfect, I have to explicitly new a form class inside the action, I think what I want is the code like this

sub add :Path(/add) :Form('add') {
        ### now we have a form object already some where, in stash for example
        ### do what ever we can
        $form->validate_and_update

  }

Maybe I can write a ActionRole for my purpose, I still need some time to try that.

perl5.14.0发布

perl5.14.0于UTC时间2011年5月14发布[1,2,3],perl自5.10发布的时间轴如下:

  • 5.10 2007/12/18
  • 5.11 2009/08/02
  • 5.12 2010/04/12
  • 5.13 2010/05/20
  • 5.14 2011/05/14

扫描了一下perldelta,值得注意的更改有

  • unicode6.0的支持
  • IPv6的支持
  • 新的正则表达式修改符/r,可以保持原来变量不变而返回修改的结果

    $perl -E '$a = "perl", say $a =~ s/p/P/r; say $a'
           Perl
           perl
  • 数组和hash容器操作现在支持引用,比如现在可以

    push $hashref, $var;
  • 支持 package {}; 语法

更多参见perldelta文档

[1]: http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2011-05/msg00621.html [2]: http://news.perlfoundation.org/2011/05/perl-514.html [3]: http://search.cpan.org/dist/perl-5.14.0/

vim-perl@github

如果你使用vim开发perl的话,github上面的vim-perl一定对你有用

https://github.com/petdance/vim-perl

git clone下来make install即可安装上,这个包里面提供了perl,perl6,tt(template toolkit),xs的语法高亮。今天我就是在寻找折行perl模块内建pod的时候找到的这个项目,一些tip如下

"打开perl文件的折行功能
let perl_fold=1
"打开vim的tt文件的filetype
au BufNewFile,BufRead *.tt setf tt2

顺便提一下vim插件 http://www.vim.org/scripts/script.php%3Fscript_id%3D556 也是使用vim开发perl的必备工具

web开发

C360_2011-04-24_13-26-43


干了好些年SA类似的工作之后,由于各方面的原因, 最近我把大部分精力都放在web开发上面去了。
作为一个门外汉,直接使用比较成熟的开发框架比较容易上手,Perl社区里应用比较广泛的web开发framework是Catalyst,此外后起之秀还有DancerMojo。Catalyst和后两者有着截然不同的风格,catalyst注重社区代码的重用,使用了Moose这样的重量级模块,因此依赖关系相当复杂,据称安装Catalyst是一件令人头疼的事情,但根据我的经验来看,cpan和cpanm都可以很顺利的完成这项工作。而Dancer和Mojo,前者仅仅依赖少量几个模块,而后者号称只需要perl5.8.7以上版本就可以安装和运行,但这两个模块都在很大程度上重造了一些轮子。这两个框架还在开发当中,使用成熟的catalyst是比较理智的选择。

入手做web开发才发现要学的东西实在太多了,就Catalyst来说,如果不搭配上DBIx::Class那简直是暴殄天物,DBIx::Class号称是所有语言中最好用的ORM,当然我没有用过其他语言中的没有发言权。感觉与Catalyst以及相关模块,就像Vim一样,学习曲线陡峭,但如果你掌握了它,就会觉得很难离开他们了。

此外javascript也是web开发中不可缺少的一环,初接触javascript感觉这个语言设计相当奇怪,比如没有block作用域,奇技淫巧一般的面向对象实现方法(在这点上和perl很像),于是买了上图那本书作为参考。

经过一个多月的自学,我终于成功的把jquery和一些ajax的技术运用到了我的一个小作品上面,这个作品大大方便了我的工作,老板貌似对这个成果也很满意,毕竟在工作中主动创新的人实在不多(至少就本部门而言)。

我得尽快成为一个比较合格的perl web开发人员,为成为一个自由职业者添加底气。

关于devpts

devpts是linux下面的一个虚拟文件系统

mount | grep devpts
none on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)

以下是google到的解释

一些像xterm/sshd这样的程序模拟一个terminal(terminal是输入输出设备,比如我们得显示器和键盘),这里面涉及两个特殊文件: xterm等用来读取和写入数据的伪tty主设备以及应用程序(比如xterm里面的bash)用来读取>数据的伪tty从设备。

传统的方法是在/dev下面有许多字符文件。主设备叫做ptyp0, ptyp1…从设备叫做ttyp0, ttyp1…这种方法比较难于管理

当前使用的方法是devpts,此时只有一个主设备 /dev/ptmx,从设备都放在/dev/pts/下面,进程打开文件/dev/ptmx便会返回一个主设备(PTM-pseudo terminal master)的fd,并会创建/dev/pts/从设备。这样,只需要在/dev/pts上mount devpts即可获得良好的虚拟终端支持。

参考 http://www.linuxfromscratch.org/pipermail/lfs-support/2001-November/000700.html

man 4 pts

perl6 fibonacci & laziness

Fibonacci

最近在perl6 blog聚合上看到了一篇关于perl6斐波那契数列的讨论,code为

>my @fib := 1, 1, *+* ...^ * >= 100;
1 1 2 3 5 8 13 21 34 55 89

这行code应该还算清晰明了,半猜半解得也能看得明白,具体解释如下

:=

bind操作符,相当于"=“,一般用来为变量取别名,在lazyness的时候需要用bind操作符,不然就lazy不起来了。

*+*

对列表元素进行的操作,这个取两个元素的方法可能有些怪异,但回想perl5里的sort,

my @sorted_array = sort {$a <=> $b} @array;

相对比也比较类似

在perl6 s03里面有讲到,.. 操作符的强化版,可以接受一个block,也就是前面的 *+* 作为其参数

^

s03,表示取值的排除值,比如

>print $_ for ^10;
0123456789>

你还可以

>say 1 ^..^ 10
23456789

* >= 100

这个似乎不用解释,判断条件

ps: 越看synopsis越觉得perl6设计得太复杂了

Laziness

my @integers = 0..*;
 for @integers -> $i {
    say $i;
    last if $i % 17 == 0;
 }

这里@integers就是一个lazy数组,其值为0到无限,perl6在见到这个数组的时候并不会真给他分配内存,而是直到需要使用的时候,才会计算并分配相应的数据,这样避免了不必要的计算, 并且可以使用并行来提高速度.

参考 http://justrakudoit.wordpress.com/2010/12/29/perl-6-fibonacci-versus-haskell/ http://perlcabal.org/syn/S03.html http://perlgeek.de/blog-en/perl-5-to-6/12-lazyness.html

Sub::Export/Sub::Import Exporter.pm的替代工具

基本导出

一般来说平常我们都用Exporter 来导出模块的函数,比如

Export导出模块函数

package NOWAY;
use base qw/Exporter/;
our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS);
@EXPORT = qw/foo/;
@EXPORT_OK = qw/foo baa/;
@EXPORT_TAGS = qw/all => \@EXPORT_OK/;
sub foo {};
sub bar {};

使用模块

use NOWAY qw/:all/;
foo();

这些功能能够满足我们平时工作的大部分需要, 但有时候也会出现问题,比如模块a和b都提供同样一个export函数 run_code,此时Exporter的导出方法就会导致符号表混乱.

Sub::Export

使用Sub::Exporter/Sub::Import, 解决上面问题的同时还提供了更多更高级的功能!使模块的导出机制强大且灵活

BASIC

package Foo;
use Sub::Exporter -setup => {
    exports => [qw(sub1 sub2 foo1 foo2)],
    groups  => {
        sub => [qw/sub1 sub2/],
        foo => [qw/foo1 foo2/]
    }
};

以上几行代码基本上就实现了Exporter的所有功能

使用Foo.pm,重命名导入函数

use Foo sub1 => {-as => 'func1'}, foo2 => {-as =>'bar2'}

使用Foo.pm,给group添加前缀

use Foo qw/-sub/;  # group语法为 -group或 :group,推荐使用前一种
use Foo -sub => {-prefix => 'any_'};

prefix同时支持递归。后缀使用-suffix

Sub::Import

Sub::ImportSub::Exporter 的配对模块。当你使用的模块是用Exporter 来做导出工作的时候,就需要用Sub::Import来获得如Sub::Exporter一样的语法糖

Sub::Exporter系列还有很多更高级的功能,详见模块文档

参考资料 Sub::Exporter Sub::Import Sub::Exporter http://advent.rjbs.manxome.org/2009/2009-12-01.html http://advent.rjbs.manxome.org/2010/2010-12-02.html

Params::Validate 检验函数参数

perl里面没有函数原型,编写一个函数的时候,经常在函数开头进行一系列的函数参数检验,比如

手动检验参数

sub check {
     my @args = @_;
     if ($args[0] >$n) {
         die "error, arg1 should be ......";
     }
     ......
 }

Params::Validate就是为了解决这个问题而编写的一个模块,

use Params::Validate to check function paramaters

use strict;
use Params::Validate qw/:all/;

sub foo {
    validate(@_, {
            foo => 1,   #必须参数
            bar => {default =>99}, #设定默认值
            loo => {type => ARRAYREF|SCALAR}  #设定参数类型
        }
    );   
}

sub bar {
    validate_pos(@_, 1,1,(0)x(@_-2));  #位置参数检查,表明必须至少有两个参数
}

sub loo {
    validate(@_,{
            # 参数依赖关系检查,个人感觉特别有用
            passwd => {type => SCALAR, optional => 1, 
             depends => ['new_passwd']},
            new_passwd => {type => SCALAR, optional => 1}
        }
    );
}
#foo(bar => 1, loo => {msg => "hf!"});
#bar(1,1,3);
loo(passwd => 'xxxxxx');

http://search.cpan.org/~drolsky/Params-Validate-0.95/lib/Params/Validate.pm