Skip to main content Skills Marketplace Descubre y explora habilidades de IA creadas por la comunidad.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Copiar promptMostrar detalles del prompt Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/loulanyue/awesome-claude-notes --skill perl-patternsEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Descargar Zip Descargando... Más de este repositorio Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics
agent-harness-construction Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates.
Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing.
Ocupaciones relacionadas SOC
Basado en la clasificación ocupacional SOC
name perl-patterns description 现代 Perl 5.36+ 的惯用法、最佳实践和约定,用于构建稳健、可维护的 Perl 应用程序。 source_path skills/perl-patterns/SKILL.md origin ECC
现代 Perl 开发模式
适用于构建健壮、可维护应用程序的 Perl 5.36+ 惯用模式和最佳实践。
何时启用
编写新的 Perl 代码或模块时
审查 Perl 代码是否符合惯用法时
重构遗留 Perl 代码以符合现代标准时
设计 Perl 模块架构时
将 5.36 之前的代码迁移到现代 Perl 时
工作原理
将这些模式作为偏向现代 Perl 5.36+ 默认设置的指南应用:签名、显式模块、聚焦的错误处理和可测试的边界。下面的示例旨在作为起点被复制,然后根据您面前的实际应用程序、依赖栈和部署模型进行调整。
核心原则
1. 使用 v5.36 编译指令
单个 use v5.36 即可替代旧的样板代码,并启用严格模式、警告和子程序签名。
use v5.36 ;
sub greet ($name ) {
say "Hello, $name !" ;
}
use strict;
use warnings;
use feature 'say' , 'signatures' ;
warnings ;
{
( ) = ;
;
}
no
'experimental::signatures'
sub greet
my
$name
@_
say
"Hello, $name !"
2. 子程序签名 use v5.36 ;
sub connect_db ($host , $port = 5432, $timeout = 30) {
return DBI->connect ("dbi:Pg:host=$host ;port=$port " , undef , undef , {
RaiseError => 1 ,
PrintError => 0 ,
});
}
sub log_message ($level , @details ) {
say "[$level ] " . join (' ' , @details );
}
sub connect_db {
my ($host , $port , $timeout ) = @_ ;
$port //= 5432 ;
$timeout //= 30 ;
}
3. 上下文敏感性 理解标量上下文与列表上下文——这是 Perl 的核心概念。
use v5.36 ;
my @items = (1 , 2 , 3 , 4 , 5 );
my @copy = @items ;
my $count = @items ;
say "Items: " . scalar @items ;
4. 后缀解引用 use v5.36 ;
my $data = {
users => [
{ name => 'Alice' , roles => ['admin' , 'user' ] },
{ name => 'Bob' , roles => ['user' ] },
],
};
my @users = $data ->{users}->@* ;
my @roles = $data ->{users}[0 ]{roles} ->@* ;
my %first = $data ->{users}[0 ]->%* ;
my @users = @{ $data ->{users} };
my @roles = @{ $data ->{users}[0 ]{roles} };
5. isa 运算符 (5.32+) 中缀类型检查——替代 blessed($o) && $o->isa('X')。
use v5.36 ;
if ($obj isa 'My::Class' ) { $obj ->do_something }
错误处理
eval/die 模式 use v5.36 ;
sub parse_config ($path ) {
my $content = eval { path($path )->slurp_utf8 };
die "Config error: $@ " if $@ ;
return decode_json($content );
}
Try::Tiny(可靠的异常处理) use v5.36 ;
use Try::Tiny;
sub fetch_user ($id ) {
my $user = try {
$db ->resultset('User' )->find($id )
// die "User $id not found\n" ;
}
catch {
warn "Failed to fetch user $id : $_ " ;
undef ;
};
return $user ;
}
原生 try/catch (5.40+) use v5.40 ;
sub divide ($x , $y ) {
try {
die "Division by zero" if $y == 0 ;
return $x / $y ;
}
catch ($e ) {
warn "Error: $e " ;
return ;
}
}
使用 Moo 的现代 OO 优先使用 Moo 进行轻量级、现代的面向对象编程。仅当需要 Moose 的元协议时才使用它。
package User;
use Moo;
use Types::Standard qw(Str Int ArrayRef) ;
use namespace::autoclean;
has name => (is => 'ro' , isa => Str, required => 1 );
has email => (is => 'ro' , isa => Str, required => 1 );
has age => (is => 'ro' , isa => Int, default => sub { 0 });
has roles => (is => 'ro' , isa => ArrayRef[Str], default => sub { [] });
sub is_admin ($self ) {
return grep { $_ eq 'admin' } $self ->roles->@* ;
}
sub greet ($self ) {
return "Hello, I'm " . $self ->name;
}
1 ;
my $user = User->new(
name => 'Alice' ,
email => 'alice@example.com' ,
roles => ['admin' , 'user' ],
);
package User;
sub new {
my ($class , %args ) = @_ ;
return bless \%args , $class ;
}
sub name { return $_ [0 ]->{name} }
1 ;
Moo 角色 package Role::Serializable;
use Moo::Role;
use JSON::MaybeXS qw(encode_json) ;
requires 'TO_HASH' ;
sub to_json ($self ) { encode_json($self ->TO_HASH) }
1 ;
package User;
use Moo;
with 'Role::Serializable' ;
has name => (is => 'ro' , required => 1 );
has email => (is => 'ro' , required => 1 );
sub TO_HASH ($self ) { { name => $self ->name, email => $self ->email } }
1 ;
原生 class 关键字 (5.38+, Corinna) use v5.38 ;
use feature 'class' ;
no warnings 'experimental::class' ;
class Point {
field $x :param ;
field $y :param ;
method magnitude () { sqrt ($x **2 + $y **2 ) }
}
my $p = Point->new(x => 3 , y => 4 );
say $p ->magnitude;
正则表达式
命名捕获和 /x 标志 use v5.36 ;
my $log_re = qr{
^ (?<timestamp> \d{4} -\d{2} -\d{2} \s \d{2} :\d{2} :\d{2} )
\s+ \[ (?<level> \w+ ) \]
\s+ (?<message> .+ ) $
}x ;
if ($line =~ $log_re ) {
say "Time: $+ {timestamp}, Level: $+ {level}" ;
say "Message: $+ {message}" ;
}
if ($line =~ /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+\[(\w+)\]\s+(.+)$/ ) {
say "Time: $1 , Level: $2 " ;
}
预编译模式 use v5.36 ;
my $email_re = qr/^[A-Za-z0-9._%+-]+\@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/ ;
sub validate_emails (@emails ) {
return grep { $_ =~ $email_re } @emails ;
}
数据结构
引用和安全深度访问 use v5.36 ;
my $config = {
database => {
host => 'localhost' ,
port => 5432 ,
options => ['utf8' , 'sslmode=require' ],
},
};
my $port = $config ->{database}{port} ;
my $missing = $config ->{cache}{host} ;
my %subset ;
@subset {qw(host port) } = @{$config ->{database}}{qw(host port) };
my @first_two = $config ->{database}{options} ->@[ 0 , 1 ];
use feature 'for_list' ;
no warnings 'experimental::for_list' ;
for my ($key , $val ) (%$ config) {
say "$key => $val " ;
}
文件 I/O
三参数 open use v5.36 ;
use autodie;
sub read_file ($path ) {
open my $fh , '<:encoding(UTF-8)' , $path ;
local $/ ;
my $content = <$fh >;
close $fh ;
return $content ;
}
open FH, $path ;
open FH, "< $path " ;
使用 Path::Tiny 进行文件操作 use v5.36 ;
use Path::Tiny;
my $file = path('config' , 'app.json' );
my $content = $file ->slurp_utf8;
$file ->spew_utf8($new_content );
for my $child (path('src' )->children(qr/\.pl$/ )) {
say $child ->basename;
}
模块组织
标准项目布局 MyApp/
├── lib/
│ └── MyApp/
│ ├── App.pm # 主模块
│ ├── Config.pm # 配置
│ ├── DB.pm # 数据库层
│ └── Util.pm # 工具集
├── bin/
│ └── myapp # 入口脚本
├── t/
│ ├── 00-load.t # 编译测试
│ ├── unit/ # 单元测试
│ └── integration/ # 集成测试
├── cpanfile # 依赖项
├── Makefile.PL # 构建系统
└── .perlcriticrc # 代码检查配置
导出器模式 package MyApp::Util;
use v5.36 ;
use Exporter 'import' ;
our @EXPORT_OK = qw(trim) ;
our %EXPORT_TAGS = (all => \@EXPORT_OK );
sub trim ($str ) { $str =~ s/^\s+|\s+$//gr }
1 ;
工具
perltidy 配置 (.perltidyrc) -i=4 # 4 空格缩进
-l=100 # 100 字符行宽
-ci=4 # 续行缩进
-ce # else 与右花括号同行
-bar # 左花括号与语句同行
-nolq # 不对长引用字符串进行反向缩进
perlcritic 配置 (.perlcriticrc) severity = 3
theme = core + pbp + security
[InputOutput::RequireCheckedSyscalls]
functions = :builtins
exclude_functions = say print
[Subroutines::ProhibitExplicitReturnUndef]
severity = 4
[ValuesAndExpressions::ProhibitMagicNumbers]
allowed_values = 0 1 2 -1
依赖管理 (cpanfile + carton) cpanm App::cpanminus Carton
carton install
carton exec -- perl bin/myapp
requires 'Moo' , '>= 2.005' ;
requires 'Path::Tiny' ;
requires 'JSON::MaybeXS' ;
requires 'Try::Tiny' ;
on test => sub {
requires 'Test2::V0' ;
requires 'Test::MockModule' ;
};
快速参考:现代 Perl 惯用法 遗留模式 现代替代方案 use strict; use warnings;use v5.36;my ($x, $y) = @_;sub foo($x, $y) { ... }@{ $ref }$ref->@*%{ $ref }$ref->%*open FH, "< $file"open my $fh, '<:encoding(UTF-8)', $fileblessed hashrefMoo 带类型的类$1, $2, $3$+{name} (命名捕获)eval { }; if ($@)Try::Tiny 或原生 try/catch (5.40+)BEGIN { require Exporter; }use Exporter 'import';手动文件操作 Path::Tinyblessed($o) && $o->isa('X')$o isa 'X' (5.32+)builtin::true / falseuse builtin 'true', 'false'; (5.36+, 实验性)
反模式
open FH, $filename ;
my $obj = new Foo(bar => 1 );
my $obj = Foo->new(bar => 1 );
map { process($_ ) } grep { validate($_ ) } @items ;
my @valid = grep { validate($_ ) } @items ;
my @results = map { process($_ ) } @valid ;
no strict 'refs' ;
${"My::Package::$var " } = $value ;
our $TIMEOUT = 30 ;
use constant TIMEOUT => 30 ;
eval "require $module " ;
eval "use $module " ;
use Module::Runtime 'require_module' ;
require_module($module );
记住 :现代 Perl 是简洁、可读且安全的。让 use v5.36 处理样板代码,使用 Moo 处理对象,并优先使用 CPAN 上经过实战检验的模块,而不是自己动手的解决方案。
原文
导航