----
presentation_topic: Perl 6: 有的沒的
presentation_title: Perl 6 The Ultimate
presentation_date: March 27th, 2005
----
眾人為彼造新舟 A ship then new they built for him
鑄以祕銀精靈璃 Of mithril and of elven-glass
船首閃耀何需槳 With shining prow; no shaven oar
銀桅未有風帆繫 Nor sail she bore on silver mast;
無雙寶鑽作燈炬 The Silmaril as lantern light
旗幟輝煌展生焰 And banner bright with living flame
映照燃星雅碧綠 To gleam thereon by Elbereth
神祇乘梭下九天... Herself was set, who thither came...
-- Pugs 源碼, src/Main.hs
----
== 第一紀元
* Perl 1.0: 1987 冬
** @array, %hash, $scalar, `/regex/`
** sub name { ... }, ('list'), <FILE>
+* Perl 2.0: 1988 夏
** foreach, sort, do "file"
** perl -w, local($var)
----
== 第一紀元
* Perl 3.0: 1989 秋
** GPL, pack/unpack
** &sub, undef
** package, "interpolated $s @a", sockets
+* Perl 4.0: 1991 春
** "Programming Perl"
** Artistic License
** caller, qx//, 0 + @array
----
== 第二紀元
* Perl 5.0: 1994 冬
** OO, POD, my($var), $Package::var
** use Module, (name => "value"), tie($scalar)
+* Perl 5.1: 1995 春
** sub { ... }
** `$SIG{__WARN__}`, `$SIG{__DIE__}`
----
== 第二紀元
* Perl 5.2: 1996 春
** sub name ($$;$) { ... }
** use overload
+* Perl 5.4: 1997 春
** $code->(@args), use 5.004;
** UNIVERSAL::isa(), UNIVERSAL::can()
----
== 第三紀元
* Perl 5.5: 1998 夏
** B::*, threads
** tie(@array)
+* Perl 5.6: 2000 春
** use utf8
** use warnings
** open $fh
----
== 第三紀元
* Perl 5.8: 2002 秋
** Encode, PerlIO, iThreads, Test::More
+* Perl 5.10: 2005 冬?
** 引入 Perl 6 語法
** CPANPLUS, Module::Build, lexical pragma
----
== 世紀末駱駝革命
* 2000 年夏, 5.6 剛發佈
+* 脆弱的多執行緒和萬國碼支援
+* 疊疊樂: 挖舊功能填新功能
+* p5p 內鬥, Topaz 計劃失敗
+* "南瓜王說了算" 開發模式難以延展
+* 社群渙散, 沒有新專案出現
+* Perl 5 己經到了壽命的極限
----
== Perl 5 架構的限制
* "向下相容" 嚴重阻礙開發
+* 核心源碼與 XS 難以維護
+* 直譯器太佔記憶體, 牽一髮動全身
+* 低階運算速度不夠快
+* 難以同時取用某個模組的多個版本
----
== Perl 5 語言的限制
* 舊版語法和新的語義難以彌合:
@a %h $s
$a[0] $h{'!'}
$obj->method
+* 造成許多不便:
sub render {
my $self = shift;
my %opts = @_;
foreach my $item (@{$self->{_attributes}}) {
print "Out: @{[$item->render(@opts{qw( x y z )}]}...\n";
}
}
----
== 新世紀福音駱駝
* 更快速: 編譯成 JIT 機器碼, 可在嵌入式系統內執行
+* 更相容: 直接呼叫 Perl5/C/Java/PHP/Python/Ruby 程式庫
+* 更簡潔: 大幅縮短常用的語法
+* 更強力: 內建物件導向, 函數導向, 文件導向, 邏輯導向系統
+* 更穩定: 核心簡潔有力, 不易出錯
+* 更可塑: 自定算符, 語法, 方言, 規則...
----
== 來看看 Perl 6
+* "Never do live demo!"
+* Live demo: Test.pm
+* Live demo: mandel.p6 vs mandel.p5
+* Live demo: hanoi, quicksort
+* Live demo: tetris.pmc
----
== 三大項
* Perl 6: 語言規範
** Synopses/Apocalypses/Exegeses
+* Parrot: 執行環境
** Parrot Design Documents
** 0.1.2 版: 2005-03-06
+* Pugs: 編譯器
** Pugs Apocrypha
** 6.0.13 版: 2005-03-26
----
== 三小項
* Ponie: Perl5 直譯器
+* PPD: Perl5 翻譯器
+* PGE: Rules 編譯器
----
== 常見問題
* 現在有哪些 Perl 6 程式可以跑?
+* CPAN 上的模組還能不能用?
+* Perl 5 會不會停止開發維護?
+* Perl 6 是否得要從頭學起?
+* Perl 6 的規格什麼時候纔會底定?
+* 我想幫忙, 該怎麼做?
----
== Perl 6
----
== Perl 6: 一步步造世界
以下主要在 perl6-language@perl.org 上進行:
0 廣徵 RFC, 彙集各種主意
+0 分組腦力激盪, 提出完整的規格建議
+0 Larry 將 RFC 分出章節, 逐一寫出啟示錄
+0 設計團隊寫出相應的注疏, 提供範例
+0 社群對啟示錄及注疏提出建議
+0 設計團隊根據回應, 整理出綱要
+0 實作團隊進行初步實作
+0 設計團隊根據實作結果, 更新綱要內容
+0 實作團隊進行後續實作
...如此直到 6.0.0 誕生為止.
----
== Perl 6: 以簡馭繁
* 霍夫曼編碼: 易行即行, 難行能行
say "Hello, World!" if $x == any(1..3);
sub unfinished { ... }
+* 在各種極端間求取平衝
# 太多算符
^%+ !@== ?/ **~* ^^; -_-$
# 太少算符
assign(a, add(multiply(3, 4), 5))
+* 吸收外來語, 尊重各種文化的差異
----
== Perl 6: 水床理論
* 此消
+* 彼長
+* 複雜度恆為定值
----
== Perl 6: 避免破音字
* 如果 "cat" 這個詞是 "tog"...
* 凸顯視覺差異:
** eval "..." / try { ... }
** for @a { ... } / loop (;;) { ... }
** sub a { ... } / method b { ... }
----
== Perl 6: 自由
* 給程式員最大的自由
+* 要靠習俗, 不設定律
+* 保持語言的彈性
+* 隨時反應環境的需求
** 可變式剖析器
** 共存的方言架構
** 多樣文件格式
** 使用者自定的 "核心功能"
+* 因應二十年以上的長程需求
----
== Perl 6: DWIM
* 隨我所欲: Do What I Mean
+* 讓 Perl 更像話
** class Dog is Animal { has $.tail }
** m:3rd:w/word/
+* 不一定要用標準英文
** m:3st:w/word/
** m:nth(3):w/word/
+* 甚至不一定要用英文
** «甲 乙 丙» ¥ (1..3);
** 書 -> 每頁 { 翻(頁) }
----
== Perl 6: 文件模型
* 透過 %=POD 來存取各種內嵌資料
** POD
** Kwid
** XML
** YAML
** Latex
* 透過共通的 DOM 互相轉換
----
== Perl 6: 變數符號
* 符號成為變數名稱的一部份
$scalar, @array, %hash
@array[3] # 不再是 $array[3]
%hash{'key'} # 也可以寫成 %hash<key>
+* 因此陣列和雜湊也可以當物件用了!
%hash.keys
@array.sort
----
== Perl 6: 點號
* 常用的小箭頭縮短成點號了
$obj.method()
$a_ref.[1] # 也可以省略成 $ref[1]
$h_ref.<key> # $h_ref<key>, $h_ref{'key'}
$c_ref.() # $c_ref()
+* 點號也可以用來呼叫一般的函式
say("Hello, World!"); # 這樣可以
"Hello, World!".say; # 這樣也可以
----
== Perl 6: 方法
* 簡單好記的方法
@array.elems # 取代了 scalar(@array)
$string.chars # 取代了 length($string)
$string.bytes # 取代了 bytes::length($string)
@array.bytes # ... 在 Perl 5 裡寫不出來 Orz
&function.arity # ... 這個也做不到 XD
* 比原來的寫法好記多了
----
== Perl 6: 具名參數
* 原來的寫法依然適用
sub sum {
my $sum;
$sum += $_ for @_;
return $sum;
}
+* 新增各種具名參數
sub clean ($text, $method) { ... } # 傳址
sub by_value ($text is copy) { ... } # 傳值
sub some_opt ($req, ?$opt = $req) { ... } # 選用
sub modify ($text is rw) { ... } # 可讀寫
sub typed (Int $num, Str $txt) { ... } # 具型別
----
== Perl 6: 呼叫函式
* 不攤平
sub whole (@names, %flags) { ... }
whole(@n, %f);
whole(names => ['a', 'b', 'c'], flags => { x => 1 });
whole(:names<a b c>, :flags{ :x });
+* 攤平
sub flat ($first, $second) {...}
flat(*@array);
sub flat (*@array) {...}
flat($first, $second);
----
== Perl 6: 高階函式
* 利用 .assuming 進行局部調用 (currying):
sub times ($x, $y) { $x * $y }
$sixtimes = ×.assuming(:y(6));
$sixtimes(9); # 54
+* 自動提取參數:
sub distance { sqrt( $^a ** 2 + $^b ** 2 ) }
@array.sort:{ $^y <=> $^x };
----
== Perl 6: 多重分派函式
* 依型別分派
multi sub add (Int $a, Int $b) {...}
multi sub add (Num $a, Num $b) {...}
multi sub add (Str $a, Str $b) {...}
+* 依值分派
multi sub factorial (0) { 1 }
multi sub factorial ($n) { $n * factorial($n - 1) }
----
== Perl 6: 算符
* 新算符
say =<README.txt>; # 讀取算符
...; # 啦啦啦算符
+* 萬國碼算符
sub prefix:<Σ> (@x) { sum(@x) }
sub postfix:<!> ($n) { ($n < 2) ?? 1 !! $n * ($n-1)! }
say( Σ 1..5! ); # 7260
(1, 2) ¥ ('a', 'b'); # (1, 'a', 2, 'b')
+* 延伸既有算符
if $x > $y > $z { ... }
if -r -w 'file' { ... }
----
== Perl 6: 數值與真值
* 數值語境
$number = +$string;
+* 真值語境
$true = ?$complex;
+* 三元算符
$x ?? $y !! $z;
----
== Perl 6: 字串
* 字串語境與接合
$string = ~$number;
$line = "Blue" ~ $moon;
$ice ~= "cream";
+* 字串安插
"Hello, $person";
"You can call &subs() and $obj.methods() too!";
"The attribute is %obj.keys.sort.reverse().";
"Two plus Two is just { 2 + 2 }.";
+* 字串格式化
$string.as('%10s');
@array.as('<strong>%03d</strong>', "<br />);
%hash.as('* %s: %s', "\n");
----
== Perl 6: 邏輯算符
* 短路與長路
$var = 9 || 3; # 9
$bool = 9 ?| 3; # Bool::True
$true = 9 +| 3; # 11
$str = 9 ~| 3; # ";"
+* 斜體的 || 表示 defined or
$arg //= 3;
$fh = open("file") err die $!;
----
== Perl 6: 超維算符
* 雙向超維
(1,1,2,3,5) »+« (1,2,3,5,8); # (2,3,5,8,13)
+* 單向超維
@objects ».run();
+* 自動昇維
('a'..'c') »x« 3; # ('aaa', 'bbb', 'ccc')
----
== Perl 6: 分叉算符
* 常用簡寫
$options = '--help' | '-d' | '-e';
if all($x, $y, $z) eq $options { ... }
# 在 Perl 5 裡要寫成:
if (($x eq "--help" || $x eq "-d" || $x eq "-e") and
($y eq "--help" || $y eq "-d" || $y eq "-e") and
($z eq "--help" || $z eq "-d" || $z eq "-e")) { ... }
+* 質數測試
sub is_prime (Int $n) { $n % all(2 .. sqrt($n)+1) }
sub has_twin (Int $n) { is_prime($n & ($n + (2 | -2))) }
----
== Perl 6: 賦名算符
* 不用再學難懂的 glob 了
&alias := ⊂
$alias := $scalar;
@alias := @array;
$alias := @array[2]{'many'}{'keys'};
+* 強大的惰性求值
@fib := (1, 1, @fib »+« @fib[1..Inf])
# (1, 1, 2, 3, 5, 8, 13...)
----
== Perl 6: 比對算符
* 比 `=~` 更聰明
$value ~~ /blue/;
$number ~~ 5..10;
$string ~~ 'hello';
+* 不祗能處理純量
@array ~~ /red/;
$key ~~ %hash;
$item ~~ @array;
----
== Perl 6: Switch
* 用 given/when 進行比對
given $string {
when 'a' .. 'z' { ... }
when all(/foo/, /bar/) { ... }
when .is_very_long { ... }
default { ... }
}
* given/when 和 ~~ 用的是同樣的機制
----
== Perl 6: 迴圈
* foreach 現在一律寫成 for
for @people -> $person {
say "Hello, $person";
}
+* for 可以一次提取多個值
for %ages.kv -> $name, $age {
say "$name is now $age";
}
for zip(@a,@b) -> $a, $b {
say "Are you $a or $b?";
}
+* C 語言的 for 改成 loop
loop ($i = 1; $i < 5; $i++) { ... }
loop { do_forever() }
----
== Perl 6: 例外
* 統一使用 `$!` 例外變數, 停用 `$@`, `$?`, `$^E`
system("rm -rf /") err die $!;
+* eval {} 現在寫成 try {}
try {
may_throw_exception();
CATCH { when Error::Nasty {...} }
}
----
== Perl 6: 類別
* 類別宣告
class Tree { method nodes { ... } }
+* 繼承
class Leaf is Tree {
has $.val;
method nodes { .val }
}
----
== Perl 6: 屬性
* 從 `has $.val` 自動產生建構式和存取式
my $x = Leaf.new(:val<Hello>);
say $x.val; # "Hello"
+* 指定屬性的類別
class Branch is Tree {
has Tree $.left;
has Tree $.right;
method nodes { (nodes .left, nodes .right) }
}
----
== Perl 6: 角色
* 可隨時混進 (mixin) 的實作界面
role Storable {
method freeze { ... }
method thaw { ... }
}
+* 用 does 和 but 來混進角色
class TreeFile is Tree does Storable { ... }
my $var = Leaf.new(:val(3)) but Storable;
my $num = 0 but true;
----
== Perl 6: 規則
* 原有的 `m//`, `s///`, `//` 語法
if $text ~~ /blue/ {...}
$name ~~ s/Dan/Chip/;
m:perl5/(\()?[^()]+(?(1)\))/;
+* 後綴修飾符改為前綴
m:i/yes/ # 忽略大小寫
s:g/a/b/ # 整批代換
+* 自動忽略空白和註解 (如同 Perl 5 的 //x)
m{ Larry # perl6
| Chip # parrot
| Autrijus # pugs
};
----
== Perl 6: 新的規則用法
* qr// 改寫成 rx//
$myrule = rx/[yn]/
+* 匿名和具名規則
$myrule = rule {\w\s+\w}
rule myrule {\w\s+\w}
+* 規則包含規則
rule name { Larry | Chip | Autrijus }
rule project { perl6 | parrot | pugs }
rule description :w { <name> does this <project> }
----
== Perl 6: 文法
* 文法/規則 =:= 物件/方法
+* 給規則一個命名空間
grammar URI {
rule reserved { <[;/?:@&=+$,\[\]]> };
rule mark { <[-_.!~*'()]> };
rule unreserved { rule { <[A-Za-z0-9]+<mark>> };
rule scheme { <[a-zA-Z]><[a-zA-Z0-9.+-]>* };
rule uri { <+<reserved>+<unreserved>+["%"]> };
}
+* Perl 6 本身也是一個文法!
grammar Perl6 {
rule statement { ... }
rule identifier { ... }
}
----
== Perl 6: 一以貫之
* 易學易用
+** ...以簡馭繁
+* 特色鮮明
+** ...相互一致
+* 兼採百家
+** ...自有韻味
+* 當下實用
+** ...萬世流芳
+* 讓 Perl 更像 Perl
----
== Parrot
----
== Parrot: 愚人節幻夢成真
* 什麼是 Parrot?
+* Perl 6 的虛擬機器
+* 也可以跑 Python, Ruby, Scheme, Forth, BASIC
+* 比 Java / .Net 適合執行動態語言
+* 大學課程
+* (開發人數 etc)
----
== Parrot: 下載安裝
* 取得穩定版本
+* 開發版本
% cd parrot
% perl Configure.pl
% make
% make test
% make install
----
== Parrot: 組合語言
* 高階組語
** IMC (Intermediate Code)
** 給編譯器使用的語言
+* 低階組語
** PASM (Parrot Assembly)
** 內部執行的語言
+* 機器碼
** PBC (Parrot Bytecode)
** 低階組語的二進制表示法
----
== Parrot: 暫存器
* 直接對應到 CPU 上的暫存器:
** $I0 整數
** $N0 浮點數
** $S0 字串
+* Parrot Magic Cookie:
** $P0 物件
** 自動處理繼承, 方法, 創生, 消滅
----
== Parrot: 變數
* 用暫存器當變數
$I1 = 5
$S42 = "Hello, World\n" # 數量不限
+* 具名的區域變數和函式
# 存成 hello.pmc 就可以用 parrot 跑了
.sub _main
.local string hello
hello = "Hello, World\n"
print hello
.end
----
== Parrot: 控制結構
* 簡單的迴圈:
# loop ($x = 5; $x > 0; $x--) { print $x }
x = 5
REDO: # 迴圈開始
unless x > 0 goto LAST
print x
dec x
goto REDO
DONE: # 迴圈結束
+* 標記還可以存到 Continuation 物件裡
.local pmc last
last = new Continuation
set_addr last, DONE
invoke last
----
== Parrot: 函式
* 簡單的函式:
# sub foo (Int $x) { my $y = $x * 5; return $y }
.sub _foo
.param int x
.local int y
y = x * 5
.return ( y )
.end
+* 呼叫函式:
$I1 = _foo(3)
print $I1 # 顯示 15
----
== Parrot: 進階函式
* 多值函式
.param int bar
.param int bur
...
.return ( baz, buz )
...
( $I1, $I2 ) = _foo( 5, 7 )
+* 方法呼叫
( $I1, $I2 ) = obj."_foo"( 5, 7 )
----
== Parrot: 程式庫
* 載入程式庫
load_bytecode "/path/to/lib/Foo.pir"
+* 取得其中的函式
.local pmc here
find_global here, "Foo", "there"
+* 呼叫函式
result = here( 1, 2 )
----
== Parrot: 呼叫外部程式庫
* 直接取用系統上的 `.so` 或 `.dll`
loadlib libsdl, 'libSDL'
$I0 = typeof libsdl
dlfunc sdl_function, libsdl, 'SDL_Init', 'ii'
store_global 'SDL::NCI', 'Init', sdl_function
dlfunc sdl_function, libsdl, 'SDL_SetVideoMode', 'piiil'
store_global 'SDL::NCI', 'SetVideoMode', sdl_function
+* 立刻可以呼叫
find_global $P0, "SDL::NCI", "Init"
$P0 (0, 0)
----
== Parrot: 待辦事項
* 抽象語法樹
+* 編碼轉換
+* 非同步式輸出入
+* 物件例外處理
+* 多重分派函式
----
== Pugs
----
== Pugs: 下載安裝
* 6.0.13 剛剛釋出了!
+* 需要先裝 GHC:
+* 取得開發中版本
% cd pugs
% perl Makefile.PL
% make
% make test
% make install
----
== Pugs: 發展沿革
* 2005 年 2 月 1 日開始 (今天是第 55 天)
+* 我學 Haskell 和 TaPL 的習作
+* 詳見 pugscode.org 上連到的 perl.com 訪問稿
+* 超快的開發速度
----
== Pugs: 直譯模式
* 命令列界面
% pugs -e "'Hello, world!'.say"
Hello, world!
% pugs examples/japh/madgolfer.p6
Just another Pugs hacker,
+* 互動式界面
% pugs
pugs> { $_ ?? $_ * &?BLOCK( $_ - 1 ) !! 1 }.(10)
3628800
----
== Pugs: 編譯模式
* 三種編譯後端
% pugscc examples/hanoi.p6
% pugscc --haskell -e "'Hello, world!'.say"
% pugscc --parrot examples/mandel.p6
+* 即時執行
% pugscc --runparrot examples/mandel.p6
----
== Pugs: 開發模式
* 先斬後奏: JFDI!
* Wiki 式開發團隊
+* 要成為 committer, 祗有兩個條件:
** 有能力也有意願幫忙
** 可以跟其他團隊成員溝通
+* 測試先行
** 高爾夫先行
+* 吸引了一大堆瘋子
----
== Pugs: 文件
* Pugs 外典
+* Kwid 文件格式
+** Kwiki 語法
+** 這張簡報就是用 Kwid 寫的
+* README 和 HOWTO
----
== Pugs: 測試
* t/ 目錄: 3000+ 個單元測試
+** 如何開始寫測試
+* examples/ 目錄: 40+ 個整合測試
+** 如何開始寫範例
+* util/ 目錄: 測試報告產生器
----
== Pugs: 內建模組
* Test.pm
* File::Spec
* SHA1
----
== Pugs: 移植中模組
* 目前有 22 個模組
Algorithm-Dependency Algorithm-FloodControl
Algorithm-MarkovChain Algorithm-NaiveBayes
Algorithm-TokenBucket CGI-Lite Commands-Guarded
Config-Tiny Email-Envelope Email-Simple File-Basename
File-Spec Geo-Distance Getopt-Std Locale-KeyedText
MIME-Lite Mail-Address SQL-Routine Sample-Module
Tree-Simple URI URI-Find
+* 即將登場: DBI::PurePerl, HTTP::Server::Simple, YAML...
----
== Pugs: 內嵌其他語言
* Inline
** Haskell
** C
+* Embed
** Perl5
** Parrot
** Ponie
----
== Pugs: 內部架構
* Main: 主程式
* Run: 執行器
* Compile: 編譯器
* AST: 語法樹
* Bind/Junction
* Extern/Embed
* Parser/Lexer
----
== Pugs: 6.2 版規劃
* 基本輸出入與流程控制元件
+* 可覆寫變數 (mutable variables)
+* 賦值 (assignment)
+* 即時編譯器 (on-the-fly compilation)
+* 即將釋出
----
== Pugs: 6.28 版規劃
* 物件導向核心
+* 類別 (classes)
+* 繼承 (inheritance)
+* 特質 (traits)
+* 型別 (types)
+* 子型別 (subtyping)
+* 內觀 (introspection)
----
== Pugs: 6.283 版規劃
* 邏輯剖析核心
+* 規則 (rules)
+* 文法 (grammars)
+* 回溯 (backtracking)
+* 可存延續 (serializable continuations)
----
== Pugs: 遙遠的彼端
* 6.2831
** 角色組合 (role composition)
** 其它執行時期功能
+* 6.28318
** 巨集 (macros)
+* 6.283185
** 將 Pugs 移植至 Perl 6
** 完成自舉 (bootstrapping)
----
== Pugs: 大家一起來!
* 移植模組
+* 想想範例
+* 撰寫測試
+* 翻譯文件
+* 幫忙整理 Parrot IMC
+* 學 Haskell, 改進 Pugs 核心
----
== 謝謝!