Posterous theme by Cory Watilo

Filed under: perl

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…

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的必备工具

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