Raku极简入门

3 阅读9分钟

📘 内容来源与许可声明
本文参考了 Raku 指南 。原作品采用 知识共享 署名-相同方式共享 4.0 国际许可协议 发布。 你可以在 creativecommons.org/licenses/by… 查看该许可协议的完整条款。

原文链接: raku.guide/

根据此协议,本衍生作品同样以 CC BY-SA 4.0 许可发布。

Raku简介

原名 Perl 6

  • Perl官方继任者,但作为独立语言发展
  • 现代化的语法和特性
  • 并发编程支持更好
  • 项目主页:raku.org

Raku is a high-level, general-purpose, gradually typed language. Raku is multi-paradigmatic. It supports Procedural, Object Oriented, and Functional programming. Raku是高层、通用、多范式和逐渐类型的语言,它可以进行过程式、面对对象和函数式编程。

安装

windows下安装:rakudo.org/downloads/s…

Linux下安装:

mkdir ~/rakudo && cd $_
curl -LJO https://rakudo.org/latest/star/src
tar -xzf rakudo-star-*.tar.gz
mv rakudo-star-*/* .
rm -fr rakudo-star-*

./bin/rstar install

echo "export PATH=$(pwd)/bin/:$(pwd)/share/perl6/site/bin:$(pwd)/share/perl6/vendor/bin:$(pwd)/share/perl6/core/bin:$PATH" >> ~/.bashrc
source ~/.bashrc

Raku极简入门 / Raku Quick Start Guide

1. 运行Raku代码 / Running Raku Code

中文:在终端中运行raku命令可进入REPL(交互式环境),在提示符>后输入语句并按回车执行。

English: Run the raku command in the terminal to start the REPL (Read-Eval-Print Loop), then type statements after the > prompt and press Enter.

# 进入REPL / Start REPL
# 在终端输入 / In terminal type:
# $ raku

> say "Hello, Raku!"
# 输出 / Output: Hello, Raku!

> my $result = 10 + 20
> say $result
# 输出 / Output: 30

中文:要执行Raku程序文件,使用raku 文件名.raku命令。

English: To execute a Raku program file, use the command raku filename.raku.

# 假设有文件hello.raku / Assuming hello.raku exists
$ cat hello.raku
say "Hello from a file!";

$ raku hello.raku
# 输出 / Output: Hello from a file!

2. 输出语句 / Output Statements

中文say语句用于输出信息,支持后缀条件判断。

English: The say statement outputs information and supports postfix conditionals.

# 基础输出 / Basic output
say "Hello, World!";  # Hello, World!

# 条件输出 / Conditional output
my $verbose = True;
say "Debug information" if $verbose;  # 输出 / Outputs

my $error = False;
say "Error occurred" if $error;  # 无输出 / No output

# 输出表达式结果 / Output expression results
say 2 + 3 * 4;  # 14
say "The answer is ", 42;  # The answer is 42

# print 与 say 的区别 / Difference between print and say
print "Hello";  # 不加换行 / No newline
print " World\n";  # Hello World

say "Hello";  # 自动加换行 / Auto newline
say "World";  # Hello\nWorld\n

# printf 格式化输出 / Formatted output
printf "Pi is approximately %.2f\n", 3.14159;  # Pi is approximately 3.14

3. 代码块与作用域 / Code Blocks and Scope

中文:花括号{}用于创建代码块,定义作用域。

English: Curly braces {} create code blocks and define scopes.

{
    my $local = "inside block";
    say $local;  # inside block
}
# say $local;  # 错误:变量超出作用域 / Error: variable out of scope

# 控制结构代码块 / Control structure blocks
my $x = 10;
if $x > 5 {
    say "x is greater than 5";
}

for 1..3 {
    say "Number: $_";  # $_ 是默认变量 / $_ is the default variable
}

4. 数学运算 / Mathematical Operations

中文:Raku的数学运算类似C语言,但有更多特性。

English: Raku's mathematical operations are similar to C, with additional features.

# 基础运算 / Basic operations
say 3 + 4 * 5;     # 23 (乘除优先 / multiplication before addition)
say (3 + 4) * 5;   # 35
say 10 / 3;        # 3.3333333333333335 (有理数 / rational)
say 10 div 3;      # 3 (整数除 / integer division)

# 自增自减 / Increment and decrement
my $a = 5;
$a++;              # 后增 / post-increment
say $a;            # 6

my $b = ++$a;      # 前增 / pre-increment
say $b;            # 7
say $a;            # 7

# 指数运算 / Exponentiation
say 2 ** 3;        # 8
say 4 ** 0.5;      # 2

# 比较运算 / Comparison operations
say 5 == 5;        # True
say 5 != 3;        # True
say 5 > 3;         # True
say 5 <=> 3;       # 1 (飞船操作符返回-1,0,1 / spaceship operator)

5. 数据类型操作 / Data Type Operations

中文:数值类型使用+, -等运算符,字符串使用eq, gt等运算符。

English: Numeric types use +, - operators, while strings use eq, gt operators.

# 数值运算 / Numeric operations
my $num1 = 10;
my $num2 = 3;
say $num1 + $num2;   # 13
say $num1 - $num2;   # 7
say $num1 * $num2;   # 30
say $num1 / $num2;   # 3.3333333333333335

# 字符串运算 / String operations
my $str1 = "hello";
my $str2 = "world";

say $str1 ~ $str2;           # helloworld (连接 / concatenation)
say $str1 ~ " " ~ $str2;     # hello world

# 字符串比较 / String comparison
say "apple" eq "apple";      # True
say "apple" ne "banana";     # True
say "apple" lt "banana";     # True (字典序 / lexicographic)
say "apple" gt "banana";     # False
say "apple" cmp "banana";    # Less (类似<=> / similar to <=>)

# 智能匹配 / Smart matching
say "123" ~~ /\d+/;          # True (正则匹配 / regex match)
say 123 ~~ Int;              # True (类型检查 / type check)

6. 注释 / Comments

中文:Raku支持多种注释方式。

English: Raku supports multiple comment styles.

# 单行注释 / Single line comment
say "Hello";  # 这也是注释 / This is also a comment

# 多行注释 / Multi-line comments
=begin comment
这是多行注释
可以跨越多行
This is a multi-line comment
It can span multiple lines
=end comment

# Pod文档注释 / Pod documentation comments
=begin pod
=head1 标题 / Title

这是一个段落 / This is a paragraph.

=item 项目1 / Item 1
=item 项目2 / Item 2
=end pod

# 内嵌注释 / Embedded comments
my $price = 100;          #`(这是价格注释) This is a price comment

7. 标量变量 / Scalar Variables

中文:标量变量以$开头,存储单个值。

English: Scalar variables start with $ and store a single value.

# 标量变量声明与赋值 / Scalar declaration and assignment
my $name = "Alice";
my $age = 25;
my $height = 1.65;
my $is_student = True;

say "$name is $age years old";  # Alice is 25 years old

# 类型约束 / Type constraints
my Int $count = 10;
my Str $title = "Hello";
my Numeric $value = 3.14;

# 变量插值 / Variable interpolation
my $language = "Raku";
say "Learning $language is fun!";  # Learning Raku is fun!
say 'No interpolation: $language'; # No interpolation: $language

8. 数组 / Arrays

中文:数组以@开头,存储多个值。

English: Arrays start with @ and store multiple values.

# 数组声明 / Array declaration
my @numbers = 1, 2, 3, 4, 5;
my @fruits = <apple banana orange>;
my @mixed = 1, "hello", 3.14, True;

say @numbers;        # [1 2 3 4 5]
say @fruits[0];      # apple
say @fruits[1];      # banana

# 数组操作 / Array operations
push @numbers, 6;    # 添加元素 / Add element
say @numbers;        # [1 2 3 4 5 6]

pop @numbers;        # 移除最后一个 / Remove last
say @numbers;        # [1 2 3 4 5]

unshift @numbers, 0; # 开头添加 / Add at beginning
say @numbers;        # [0 1 2 3 4 5]

# 数组切片 / Array slicing
say @numbers[0..2];  # [0 1 2]
say @numbers[^3];    # [0 1 2] (0到2 / 0 to 2)

# 数组长度 / Array length
say @numbers.elems;  # 6
say +@numbers;       # 6 (数字上下文 / numeric context)

9. 散列 / Hashes

中文:散列以%开头,存储键值对。

English: Hashes start with % and store key-value pairs.

# 散列声明 / Hash declaration
my %person = (
    name => "Bob",
    age  => 30,
    city => "New York"
);

# 简洁语法 / Concise syntax
my %colors = :red("FF0000"), :green("00FF00"), :blue("0000FF");
my %short = :red<FF0000>, :green<00FF00>, :blue<0000FF>;

# 访问元素 / Accessing elements
say %person<name>;     # Bob
say %person{"age"};    # 30
say %person<city>;     # New York

# 添加/修改元素 / Add/modify elements
%person<occupation> = "Engineer";
%person{"age"} = 31;

# 检查键是否存在 / Check if key exists
say %person<name>:exists;  # True
say %person<salary>:exists; # False

# 遍历散列 / Iterate through hash
for %person.kv -> $key, $value {
    say "$key: $value";
}

# 散列函数 / Hash functions
say %person.elems;     # 元素数量 / Number of elements
say %person.keys;      # 所有键 / All keys
say %person.values;    # 所有值 / All values

10. 控制结构 / Control Structures

# 条件语句 / Conditional statements
my $score = 85;

if $score >= 90 {
    say "优秀 / Excellent";
} elsif $score >= 60 {
    say "及格 / Pass";
} else {
    say "不及格 / Fail";
}

# 后缀形式 / Postfix form
say "满分 / Perfect" if $score == 100;

# unless 语句 / unless statement
unless $score < 60 {
    say "考试通过 / Exam passed";
}

# 循环 / Loops
for 1..5 -> $i {
    say "循环 / Loop: $i";
}

my $count = 0;
while $count < 3 {
    say "计数 / Count: $count";
    $count++;
}

# given/when (类似switch-case / like switch-case)
given "apple" {
    when "banana" { say "香蕉 / Banana" }
    when "apple"  { say "苹果 / Apple" }
    when "orange" { say "橙子 / Orange" }
    default       { say "未知水果 / Unknown fruit" }
}

11. 子程序 / Subroutines

# 定义子程序 / Define subroutine
sub greet($name) {
    return "Hello, $name!";
}

# 调用子程序 / Call subroutine
say greet("Alice");  # Hello, Alice!

# 多重分派 / Multiple dispatch
multi sub calculate(Int $x, Int $y) {
    return $x + $y;
}

multi sub calculate(Str $x, Str $y) {
    return $x ~ $y;
}

say calculate(10, 20);     # 30
say calculate("a", "b");   # ab

# 命名参数 / Named parameters
sub person-info(:$name!, :$age = 18, :$city = "Unknown") {
    return "$name, $age, from $city";
}

say person-info(name => "Charlie", age => 25, city => "London");
say person-info(name => "David");  # 使用默认值 / Uses defaults

12. 类和对象 / Classes and Objects

# 简单类定义 / Simple class definition
class Person {
    has $.name;
    has $.age;
    has $.city;
    
    method introduce() {
        say "我是 $.name,来自 $.city / I'm $.name from $.city";
    }
}

# 创建对象 / Create object
my $person1 = Person.new(
    name => "Emma",
    age  => 28,
    city => "Paris"
);

$person1.introduce();

# 继承 / Inheritance
class Student is Person {
    has $.student-id;
    has @.courses;
    
    method study($subject) {
        say "$.name 正在学习 $subject / $.name is studying $subject";
    }
}

my $student = Student.new(
    name => "Frank",
    age  => 20,
    city => "Berlin",
    student-id => "S12345",
    courses => ["Math", "Physics", "Chemistry"]
);

$student.introduce();
$student.study("Mathematics");

这个指南涵盖了Raku的基础知识,从简单的REPL使用到复杂的数据结构和面向对象编程。Raku的强大之处在于它的表现力、灵活性和丰富的内置功能。

This guide covers the basics of Raku, from simple REPL usage to complex data structures and object-oriented programming. Raku's strength lies in its expressiveness, flexibility, and rich built-in functionality.

Raku函数式编程

Raku Functional Programming

Raku函数式编程极简入门

Raku Functional Programming Quick Start

1. 一等函数 / First-Class Functions

中文: 在Raku中,函数是一等公民,可以像普通变量一样传递。

English: In Raku, functions are first-class citizens and can be passed around like ordinary variables.

# 函数作为变量 / Function as variable
my &greet = sub ($name) { "Hello, $name!" };
say greet("Alice");  # Hello, Alice!

# 箭头函数 / Arrow function
my &square = -> $x { $x ** 2 };
say square(5);       # 25

# 函数作为参数 / Function as parameter
sub apply(&func, $value) {
    func($value)
}
say apply(&square, 4);  # 16

2. 高阶函数 / Higher-Order Functions

中文: 接收或返回其他函数的函数。

English: Functions that take or return other functions.

# 返回函数的函数 / Function returning function
sub multiplier($factor) {
    return -> $x { $x * $factor }
}

my &triple = multiplier(3);
say triple(7);  # 21

# 柯里化 / Currying
sub add($x) {
    return -> $y { $x + $y }
}

my &add5 = add(5);
say add5(3);  # 8

3. map函数 / Map Function

中文: 将函数应用于列表每个元素。

English: Apply function to each element of a list.

my @numbers = 1..5;

# 使用map / Using map
my @squares = @numbers.map(-> $x { $x ** 2 });
say @squares;  # [1 4 9 16 25]

# 简洁语法 / Concise syntax
my @doubled = @numbers.map(* * 2);
say @doubled;  # [2 4 6 8 10]

# 链式调用 / Chaining
my @result = @numbers
    .map(* + 1)      # 加1 / Add 1
    .map(* * 3)      # 乘3 / Multiply by 3
    .grep(* > 10);   # 过滤大于10 / Filter > 10
    
say @result;  # [12 15 18]

4. grep函数 / Grep Function

中文: 过滤列表元素。

English: Filter list elements.

my @nums = 1..10;

# 筛选偶数 / Filter even numbers
my @evens = @nums.grep(-> $x { $x %% 2 });
say @evens;  # [2 4 6 8 10]

# Whatever表达式 / Whatever expression
my @odds = @nums.grep(* % 2 == 1);
say @odds;   # [1 3 5 7 9]

# 复杂条件 / Complex condition
my @filtered = @nums.grep({
    $_ > 5 && $_ < 8
});
say @filtered;  # [6 7]

5. reduce函数 / Reduce Function

中文: 将列表归约为单个值。

English: Reduce list to single value.

my @numbers = 1..5;

# 求和 / Sum
my $sum = @numbers.reduce(-> $acc, $val { $acc + $val });
say $sum;  # 15

# 乘积 / Product
my $product = @numbers.reduce(&infix:<*>);
say $product;  # 120

# 最大值 / Maximum
my $max = @numbers.reduce(&max);
say $max;  # 5

# 自定义归约 / Custom reduction
sub concatenate($a, $b) { $a ~ $b }
my $concat = <a b c d>.reduce(&concatenate);
say $concat;  # abcd

6. 函数组合 / Function Composition

中文: 组合多个函数创建新函数。

English: Compose multiple functions to create new one.

# 手动组合 / Manual composition
sub f($x) { $x + 1 }
sub g($x) { $x * 2 }
sub h($x) { f(g($x)) }  # f ∘ g

say h(3);  # 7 (3*2=6, 6+1=7)

# 使用∘操作符 / Using ∘ operator
sub add1($x) { $x + 1 }
sub double($x) { $x * 2 }
sub square($x) { $x ** 2 }

# 组合多个函数 / Compose multiple functions
my &pipeline = &square ∘ &double ∘ &add1;
say pipeline(3);  # 64 ((3+1)*2=8, 8²=64)

# 反向组合 / Reverse composition
my &chain = &add1 ∘ &double ∘ &square;
say chain(3);  # 19 (3²=9, 9*2=18, 18+1=19)

7. 不可变性 / Immutability

中文: Raku支持不可变数据结构。

English: Raku supports immutable data structures.

# 不可变列表 / Immutable list
my @original = 1, 2, 3;
my @modified = @original.map(* * 2);

say @original;  # [1 2 3] (未改变 / unchanged)
say @modified;  # [2 4 6]

# 绑定不可变值 / Binding immutable values
my \immutable = 42;
# immutable = 43;  # 错误: 不能修改 / Error: cannot modify

# 使用:=绑定 / Using := binding
my $x := 10;
# $x = 20;  # 错误 / Error

8. 惰性求值 / Lazy Evaluation

中文: Raku支持惰性序列。

English: Raku supports lazy sequences.

# 惰性范围 / Lazy range
my $lazy-range = 1..Inf;  # 无限序列 / Infinite sequence

# 获取前10个元素 / Take first 10 elements
my @first-ten = $lazy-range[^10];
say @first-ten;  # [1 2 3 4 5 6 7 8 9 10]

# 惰性map / Lazy map
my $squares = (1..*).map(* ** 2);  # 无限平方序列 / Infinite squares
say $squares[^5];  # [1 4 9 16 25]

# 惰性grep / Lazy grep
my $even-squares = (1..*).map(* ** 2).grep(* %% 2);
say $even-squares[^5];  # [4 16 36 64 100]

9. 闭包 / Closures

中文: 捕获外部环境的函数。

English: Functions that capture external environment.

sub make-counter($start) {
    my $count = $start;
    return {
        $count++;
    }
}

my &counter1 = make-counter(0);
my &counter2 = make-counter(100);

say counter1();  # 0
say counter1();  # 1
say counter2();  # 100
say counter1();  # 2
say counter2();  # 101

# 捕获多个变量 / Capture multiple variables
sub make-adder($x) {
    return -> $y { $x + $y }
}

my &add10 = make-adder(10);
say add10(5);  # 15
say add10(20); # 30

10. 模式匹配 / Pattern Matching

中文: Raku支持函数式模式匹配。

English: Raku supports functional pattern matching.

# 多重分派作为模式匹配 / Multiple dispatch as pattern matching
multi factorial(0) { 1 }
multi factorial(Int $n where * > 0) {
    $n * factorial($n - 1)
}

say factorial(5);  # 120
say factorial(0);  # 1

# given/when 模式匹配 / given/when pattern matching
sub classify($value) {
    given $value {
        when Int    { "整数 / Integer" }
        when Str    { "字符串 / String" }
        when *.isa(Any) { "其他 / Other" }
    }
}

say classify(42);     # 整数 / Integer
say classify("foo");  # 字符串 / String

11. Monads和Functor / Monads and Functor

中文: Raku中的Maybe Monad模式。

English: Maybe Monad pattern in Raku.

# Maybe类型实现 / Maybe type implementation
class Maybe {
    has $.value;
    
    method map(&func) {
        $.value.defined ?? Maybe.new(value => func($.value)) !! self
    }
    
    method flatmap(&func) {
        $.value.defined ?? func($.value) !! self
    }
}

# 使用示例 / Usage example
my $maybe1 = Maybe.new(value => 5);
my $maybe2 = Maybe.new(value => Nil);

say $maybe1.map(* * 2).map(* + 1).value;  # 11
say $maybe2.map(* * 2).map(* + 1).value;  # Nil (无错误 / no error)

# Option类型 / Option type
sub safe-divide($a, $b) {
    $b == 0 ?? Nil !! $a / $b
}

my $result = safe-divide(10, 2) // "无法计算 / Cannot compute";
say $result;  # 5

12. 列表推导式 / List Comprehensions

# 基本列表推导 / Basic list comprehension
my @pairs = ((1..3) X (1..3)).map(-> ($a, $b) { [$a, $b] });
say @pairs;  # [[1 1] [1 2] [1 3] [2 1] ...]

# 使用gather/take / Using gather/take
my @squares = gather {
    for 1..5 -> $n {
        take $n ** 2 if $n %% 2;
    }
};
say @squares;  # [4 16]

# 复杂推导 / Complex comprehension
my @coordinates = gather {
    for 1..3 -> $x {
        for 1..3 -> $y {
            take [$x, $y] if $x != $y;
        }
    }
};
say @coordinates.elems;  # 6

13. 函数式管道 / Functional Pipelines

# 方法链管道 / Method chain pipeline
my @data = 1..10;

my $result = @data
    .grep(* %% 2)           # 取偶数 / Take evens
    .map(* * 3)             # 乘3 / Multiply by 3
    .grep(* > 10)           # 过滤大于10 / Filter > 10
    .reduce(&[+]);          # 求和 / Sum

say $result;  # 54 (6*3 + 8*3 + 10*3)

# 使用feed操作符 / Using feed operator
my $pipeline = (1..10)
    ==> grep(* %% 2)
    ==> map(* * 2)
    ==> grep(* > 10)
    ==> reduce(&[+]);
    
say $pipeline;  # 64

14. 递归函数 / Recursive Functions

# 尾递归优化 / Tail recursion optimization
sub tail-factorial($n, $acc = 1) {
    return $acc if $n <= 1;
    tail-factorial($n - 1, $n * $acc);
}

say tail-factorial(5);  # 120

# 递归处理列表 / Recursive list processing
sub sum-list(@list) {
    return 0 unless @list.elems;
    return @list[0] + sum-list(@list[1..*]);
}

say sum-list([1, 2, 3, 4, 5]);  # 15

# 递归树处理 / Recursive tree processing
class Node {
    has $.value;
    has @.children;
}

sub sum-tree(Node $node) {
    $node.value + $node.children.map(&sum-tree).sum
}

15. 纯函数 / Pure Functions

# 纯函数示例 / Pure function example
sub pure-add($a, $b) {
    $a + $b  # 无副作用,确定性输出 / No side effects, deterministic
}

say pure-add(3, 4);  # 7
say pure-add(3, 4);  # 7 (总是相同 / Always same)

# 非纯函数 / Impure function
my $counter = 0;
sub impure-add($a, $b) {
    $counter++;
    $a + $b
}

say impure-add(3, 4);  # 7
say $counter;          # 1
say impure-add(3, 4);  # 7
say $counter;          # 2 (有副作用 / Has side effect)

Raku的函数式编程功能强大,结合了命令式和函数式的最佳特性。通过这些工具,你可以编写更简洁、可维护和可测试的代码。

Raku's functional programming features are powerful, combining the best of imperative and functional paradigms. With these tools, you can write more concise, maintainable, and testable code.

Raku 语言强项领域

Raku 语言应用

1. 文本解析与 DSL 构建

  • 核心优势:内置 Grammar 引擎,使用 PEG 解析表达式文法,支持嵌套规则和语法继承
  • 典型应用:自定义文件格式解析器、领域特定语言(DSL)、复杂日志分析工具

2. 并发与异步编程

  • 特色机制:Supply(响应式数据流)、Promise(异步任务)、Channel(线程安全队列)
  • 优势:高层抽象、内置线程安全、避免常见并发陷阱

3. 函数式编程

  • 特性支持:惰性列表、高阶函数、模式匹配、不可变数据结构
  • 应用:数据处理管道、算法实现、声明式编程

4. 系统脚本与 CLI 工具

  • 内置功能:自动命令行解析、完善错误处理、跨平台支持
  • 定位:替代 Bash/Python 的高级脚本语言

Raku 并发编程特点

性能特征

  • 轻量级:Promise 开销约 100 字节,支持大规模并发
  • 安全第一:原子操作、无锁数据结构、竞态条件防护
  • 响应式:Supply 支持背压控制,防止资源耗尽

编程模型

  • 简单启动start { 异步代码 } 创建任务
  • 优雅同步await 等待多个任务完成
  • 数据流:Supply 提供发布-订阅模式

English Introduction

Raku Language Strengths

1. Text Parsing & DSL Construction

  • Core Advantage: Built-in Grammar engine with PEG support, allows nested rules and grammar inheritance
  • Applications: Custom file parsers, Domain-Specific Languages, complex log analysis tools

2. Concurrency & Async Programming

  • Key Mechanisms: Supply (reactive streams), Promise (async tasks), Channel (thread-safe queues)
  • Advantages: High-level abstractions, built-in thread safety, avoids common concurrency pitfalls

3. Functional Programming

  • Features: Lazy lists, higher-order functions, pattern matching, immutable data structures
  • Use Cases: Data processing pipelines, algorithm implementation, declarative programming

4. System Scripting & CLI Tools

  • Built-in: Automatic CLI parsing, robust error handling, cross-platform support
  • Position: Advanced scripting language alternative to Bash/Python

Raku Concurrency Programming

Performance Characteristics:

  • Lightweight: ~100 bytes per Promise, supports massive concurrency
  • Safety First: Atomic operations, lock-free data structures, race condition protection
  • Reactive: Supply with back-pressure control prevents resource exhaustion

Programming Model:

  • Easy Start: start { async code } creates tasks
  • Graceful Sync: await waits for multiple completions
  • Data Flow: Supply provides pub-sub pattern

综合示例 / Comprehensive Example

场景:并发日志处理器

Scenario: Concurrent Log Processor

功能:同时监控多个日志文件,实时解析、过滤、聚合数据,输出统计结果 Features: Monitor multiple log files concurrently, parse in real-time, filter, aggregate, output statistics

# 定义日志语法 / Define log grammar
grammar LogGrammar {
    rule TOP { <timestamp> <level> <message> }
    token timestamp { \d**4 '-' \d**2 '-' \d**2 ' ' \d**2 ':' \d**2 ':' \d**2 }
    token level { 'INFO' | 'WARN' | 'ERROR' | 'DEBUG' }
    token message { .* }
}

# 响应式日志处理器 / Reactive log processor
class LogProcessor {
    has Str @.log-files;
    
    method start-processing {
        my $stats-supply = Supply.new;
        
        # 并发处理多个文件 / Process multiple files concurrently
        my @promises = @!log-files.map: -> $file {
            start {
                # 监控文件变化 / Monitor file changes
                for $file.IO.watch -> $change {
                    if $change ~~ /'file changed'/ {
                        self.process-file($file, $stats-supply);
                    }
                }
            }
        };
        
        # 实时统计聚合 / Real-time statistics aggregation
        my %stats;
        $stats-supply.tap: -> (:$level, :$count) {
            %stats{$level} += $count;
            
            # 每10秒输出统计 / Output stats every 10 seconds
            state $last-report = now;
            if now - $last-report > 10 {
                self.report-stats(%stats);
                $last-report = now;
            }
        };
        
        # 等待所有处理任务 / Wait for all processing tasks
        await @promises;
    }
    
    method process-file($file, $stats-supply) {
        # 并发读取和解析 / Concurrent reading and parsing
        await $file.IO.lines.map: -> $line {
            start {
                if LogGrammar.parse($line) -> $match {
                    # 发送到数据流 / Emit to stream
                    $stats-supply.emit(
                        level => ~$match<level>,
                        count => 1
                    );
                    
                    # 错误级别特殊处理 / Special handling for errors
                    if $match<level> eq 'ERROR' {
                        self.alert-error($match<message>);
                    }
                }
            }
        }
    }
    
    method alert-error($message) {
        # 异步发送警报 / Async alert sending
        start {
            # 模拟网络请求 / Simulate network request
            await Promise.in(0.1);
            say "ALERT: Error detected - $message";
        }
    }
    
    method report-stats(%stats) {
        say "\n=== 统计报告 / Statistics Report ===";
        for %stats.sort(-*.value) -> (:$key, :$value) {
            printf "%-6s: %5d 条\n", $key, $value;
        }
    }
}

# 使用示例 / Usage example
my $processor = LogProcessor.new(
    log-files => ['/var/log/app1.log', '/var/log/app2.log', '/var/log/app3.log']
);

# 启动处理 / Start processing
$processor.start-processing;

示例特点 / Example Features:

  1. 并发文件监控:同时监视多个日志文件变化 Concurrent file monitoring: Watch multiple log files simultaneously

  2. 响应式数据处理:使用 Supply 实现发布-订阅模式 Reactive data processing: Pub-sub pattern using Supply

  3. 语法解析:用 Grammar 解析结构化日志 Grammar parsing: Parse structured logs with Grammar

  4. 异步警报:错误检测后异步发送通知 Async alerts: Send notifications asynchronously after error detection

  5. 实时聚合:每10秒输出一次统计报告 Real-time aggregation: Output statistics every 10 seconds

性能优势 / Performance Advantages:

  • 并行I/O:多个文件同时读取,最大化磁盘利用率 Parallel I/O: Read multiple files concurrently, maximize disk utilization

  • 零阻塞:异步处理避免阻塞主线程 Non-blocking: Async processing avoids blocking main thread

  • 资源控制:背压机制防止内存溢出 Resource control: Back-pressure prevents memory overflow

  • 自动扩展:线程池自动管理并发任务 Auto-scaling: Thread pool manages concurrent tasks automatically

这个示例展示了 Raku 如何将文本解析、并发编程、函数式处理和系统编程优雅结合,解决实际运维场景中的复杂问题。

This example demonstrates how Raku elegantly combines text parsing, concurrency, functional programming, and system scripting to solve complex problems in real-world operational scenarios.