summaryrefslogtreecommitdiffhomepage
path: root/zh-tw
diff options
context:
space:
mode:
Diffstat (limited to 'zh-tw')
-rw-r--r--zh-tw/bash-tw.html.markdown2
-rw-r--r--zh-tw/dart-tw.html.markdown566
-rw-r--r--zh-tw/elixir-tw.html.markdown16
-rw-r--r--zh-tw/perl-tw.html.markdown328
-rw-r--r--zh-tw/pythonlegacy-tw.html.markdown (renamed from zh-tw/python-tw.html.markdown)6
5 files changed, 906 insertions, 12 deletions
diff --git a/zh-tw/bash-tw.html.markdown b/zh-tw/bash-tw.html.markdown
index 78b39f2d..5136d513 100644
--- a/zh-tw/bash-tw.html.markdown
+++ b/zh-tw/bash-tw.html.markdown
@@ -23,7 +23,7 @@ filename: LearnBash-tw.sh
lang: zh-tw
---
-Bash 是一個爲 GNU 計劃編寫的 Unix shell,是 Linux 和 Mac OS X 下預設的 shell。
+Bash 是一個爲 GNU 計劃編寫的 Unix shell,是 Linux 和 macOS 下預設的 shell。
以下大多數例子可以作爲腳本的一部分運行,也可直接在 shell 下互動執行。
[更多資訊](http://www.gnu.org/software/bash/manual/bashref.html)
diff --git a/zh-tw/dart-tw.html.markdown b/zh-tw/dart-tw.html.markdown
new file mode 100644
index 00000000..5a9241c2
--- /dev/null
+++ b/zh-tw/dart-tw.html.markdown
@@ -0,0 +1,566 @@
+---
+language: dart
+lang: zh-tw
+filename: learndart-tw.dart
+contributors:
+ - ["Joao Pedrosa", "https://github.com/jpedrosa/"]
+translators:
+ - ["Bob Lu", "https://github.com/LuPoYi/"]
+---
+
+Dart 是程式語言領域的新人。
+它借鑒了許多其他主流語言,並且不會偏離它的兄弟語言 JavaScript 太多。
+就像 JavaScript 一樣,Dart 的目標是提供良好的瀏覽器整合性。
+
+Dart 最有爭議的特性必然是它的可選類型。
+
+```javascript
+import "dart:collection";
+import "dart:math" as DM;
+
+// 歡迎進入15分鐘的 Dart 學習。 http://www.dartlang.org/
+// 這是一個可實際執行的範例。你可以用 Dart 執行它
+// 或者線上執行! 可以把程式碼複製/貼上到這個網站。 http://try.dartlang.org/
+
+// 函數宣告和方法宣告看起來一樣。
+// 函數宣告可以是巢狀的。宣告使用這種 name() {} 的形式,
+// 或者 name() => 單行表示式; 的形式。
+// 右箭頭的宣告形式會直接地返回表示式的結果。
+example1() {
+ example1nested1() {
+ example1nested2() => print("Example1 nested 1 nested 2");
+ example1nested2();
+ }
+ example1nested1();
+}
+
+// 匿名函數沒有函數名。
+example2() {
+ example2nested1(fn) {
+ fn();
+ }
+ example2nested1(() => print("Example2 nested 1"));
+}
+
+// 當宣告函數類型的參數的時候,宣告中可以包含
+// 函數參數需要的參數,指定所需的參數名即可。
+example3() {
+ example3nested1(fn(informSomething)) {
+ fn("Example3 nested 1");
+ }
+ example3planB(fn) { // 或者不宣告函數參數的參數
+ fn("Example3 plan B");
+ }
+ example3nested1((s) => print(s));
+ example3planB((s) => print(s));
+}
+
+// 函數有可以訪問到外層變數的閉包。
+var example4Something = "Example4 nested 1";
+example4() {
+ example4nested1(fn(informSomething)) {
+ fn(example4Something);
+ }
+ example4nested1((s) => print(s));
+}
+
+// 下面這個包含 sayIt 方法的類別宣告,同樣有一個可以訪問外層變數的閉包,
+// 就像前面的函數一樣。
+var example5method = "Example5 sayIt";
+class Example5Class {
+ sayIt() {
+ print(example5method);
+ }
+}
+example5() {
+ // 創建一個 Example5Class 類的匿名實例,
+ // 並呼叫它的 sayIt 方法。
+ new Example5Class().sayIt();
+}
+
+// 類別的宣告使用這種形式 class name { [classBody] }.
+// classBody 中可以包含實例方法和變數,
+// 還可以包含類別方法和變數。
+class Example6Class {
+ var example6InstanceVariable = "Example6 instance variable";
+ sayIt() {
+ print(example6InstanceVariable);
+ }
+}
+example6() {
+ new Example6Class().sayIt();
+}
+
+// 類別方法和變數使用 static 宣告。
+class Example7Class {
+ static var example7ClassVariable = "Example7 class variable";
+ static sayItFromClass() {
+ print(example7ClassVariable);
+ }
+ sayItFromInstance() {
+ print(example7ClassVariable);
+ }
+}
+example7() {
+ Example7Class.sayItFromClass();
+ new Example7Class().sayItFromInstance();
+}
+
+// 定數非常方便,但是對於在函數/方法的外層的定數有一個限制,
+// 類別的外層或外面的定數必須是常數。
+// 字串和數字預設是常數。
+// 但是 array 和 map 不是。他們需要用 "const" 宣告為常數。
+var example8Array = const ["Example8 const array"],
+ example8Map = const {"someKey": "Example8 const map"};
+example8() {
+ print(example8Array[0]);
+ print(example8Map["someKey"]);
+}
+
+// Dart 中的迴圈使用標準的 for () {} 或 while () {} 的形式,
+// 以及更加現代的 for (.. in ..) {} 的形式, 或者
+// 以 forEach 開頭並具有許多特性支援函數回呼的形式。
+var example9Array = const ["a", "b"];
+example9() {
+ for (var i = 0; i < example9Array.length; i++) {
+ print("Example9 for loop '${example9Array[i]}'");
+ }
+ var i = 0;
+ while (i < example9Array.length) {
+ print("Example9 while loop '${example9Array[i]}'");
+ i++;
+ }
+ for (var e in example9Array) {
+ print("Example9 for-in loop '${e}'");
+ }
+ example9Array.forEach((e) => print("Example9 forEach loop '${e}'"));
+}
+
+// 透過迴圈遍歷字串中的每個字元或者取出其子字串。
+var example10S = "ab";
+example10() {
+ for (var i = 0; i < example10S.length; i++) {
+ print("Example10 String character loop '${example10S[i]}'");
+ }
+ for (var i = 0; i < example10S.length; i++) {
+ print("Example10 substring loop '${example10S.substring(i, i + 1)}'");
+ }
+}
+
+// 支援兩種數字格式 int 和 double。
+example11() {
+ var i = 1 + 320, d = 3.2 + 0.01;
+ print("Example11 int ${i}");
+ print("Example11 double ${d}");
+}
+
+// DateTime 提供了日期/時間的方法。
+example12() {
+ var now = new DateTime.now();
+ print("Example12 now '${now}'");
+ now = now.add(new Duration(days: 1));
+ print("Example12 tomorrow '${now}'");
+}
+
+// 支援正規表達式。
+example13() {
+ var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$");
+ match(s) {
+ if (re.hasMatch(s)) {
+ print("Example13 regexp matches '${s}'");
+ } else {
+ print("Example13 regexp doesn't match '${s}'");
+ }
+ }
+ match(s1);
+ match(s2);
+}
+
+// 布林運算式支持隱式轉換以及動態類型
+example14() {
+ var a = true;
+ if (a) {
+ print("Example14 true, a is $a");
+ }
+ a = null;
+ if (a) {
+ print("Example14 true, a is $a");
+ } else {
+ print("Example14 false, a is $a"); // 執行到這裡
+ }
+
+// 動態類型的null可以轉換成bool型
+ var b; // b是動態類型
+ b = "abc";
+ try {
+ if (b) {
+ print("Example14 true, b is $b");
+ } else {
+ print("Example14 false, b is $b");
+ }
+ } catch (e) {
+ print("Example14 error, b is $b"); // 這段程式碼可以執行但是會報錯
+ }
+ b = null;
+ if (b) {
+ print("Example14 true, b is $b");
+ } else {
+ print("Example14 false, b is $b"); // 執行到這裡
+ }
+
+ // 靜態類型的null不能轉換成bool型
+ var c = "abc";
+ c = null;
+ // 編譯出錯
+ // if (c) {
+ // print("Example14 true, c is $c");
+ // } else {
+ // print("Example14 false, c is $c");
+ // }
+}
+
+// try/catch/finally 和 throw 語句用於例外處理。
+// throw 語句可以使用任何物件作為參數。
+example15() {
+ try {
+ try {
+ throw "Some unexpected error.";
+ } catch (e) {
+ print("Example15 an exception: '${e}'");
+ throw e; // Re-throw
+ }
+ } catch (e) {
+ print("Example15 catch exception being re-thrown: '${e}'");
+ } finally {
+ print("Example15 Still run finally");
+ }
+}
+
+// 想要有效地動態創建長字串,
+// 應該使用 StringBuffer。或者 join 一個字串的陣列。
+example16() {
+ var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e;
+ for (e in a) { sb.write(e); }
+ print("Example16 dynamic string created with "
+ "StringBuffer '${sb.toString()}'");
+ print("Example16 join string array '${a.join()}'");
+}
+
+// 字串連接只需讓相鄰的字串相連,
+// 不需要額外的操作運算符號。
+example17() {
+ print("Example17 "
+ "concatenate "
+ "strings "
+ "just like that");
+}
+
+// 字串使用單引號或雙引號做分隔,二者並沒有實際的差異。
+// 這種靈活性可以很好地避免內容中需要轉義換行的情況。
+// 例如,字串內容裡的 HTML 屬性使用了雙引號。
+example18() {
+ print('Example18 <a href="etc">'
+ "Don't can't I'm Etc"
+ '</a>');
+}
+
+// 用三個單引號或三個雙引號表示的字串
+// 可以跨越多行,並且包含換行。
+example19() {
+ print('''Example19 <a href="etc">
+Example19 Don't can't I'm Etc
+Example19 </a>''');
+}
+
+// 字串可以使用 $ 符號插入內容。
+// 使用 $ { [expression] } 的形式,表示式的值會被插入到字串中。
+// $ 跟著一個變數名會插入變數的值。
+// 如果要在字符串中插入 $ ,可以使用 \$ 的轉義形式取代。
+example20() {
+ var s1 = "'\${s}'", s2 = "'\$s'";
+ print("Example20 \$ interpolation ${s1} or $s2 works.");
+}
+
+// 可選類型允許作為 API 的標註,並且可以輔助 IDE,
+// 這樣 IDE 可以更好地提供重構、自動完成和錯誤檢測功能。
+// 目前為止我們還沒有宣告任何類型,並且程式可以執行。
+// 事實上,類型在執行時會被忽略。
+// 類型甚至可以是錯的,並且程式依然可以執行,
+// 好像和類型完全無關一樣。
+// 有一個執行時參數可以讓程式進入檢查模式,它會在執行時檢查類型錯誤。
+// 這在開發時很有用,但是由於增加了額外的檢查會使程式變慢,
+// 因此應該避免在部署時使用。
+class Example21 {
+ List<String> _names;
+ Example21() {
+ _names = ["a", "b"];
+ }
+ List<String> get names => _names;
+ set names(List<String> list) {
+ _names = list;
+ }
+ int get length => _names.length;
+ void add(String name) {
+ _names.add(name);
+ }
+}
+
+void example21() {
+ Example21 o = new Example21();
+ o.add("c");
+ print("Example21 names '${o.names}' and length '${o.length}'");
+ o.names = ["d", "e"];
+ print("Example21 names '${o.names}' and length '${o.length}'");
+}
+
+// 類型的繼承形式是 class name extends AnotherClassName {} 。
+class Example22A {
+ var _name = "Some Name!";
+ get name => _name;
+}
+class Example22B extends Example22A {}
+example22() {
+ var o = new Example22B();
+ print("Example22 class inheritance '${o.name}'");
+}
+
+// 類型也可以使用 mixin 的形式 :
+// class name extends SomeClass with AnotherClassName {}.
+// 必需繼承某個類型才能 mixin 另一個類型。
+// 當前 mixin 的模板類型不能有建構子。
+// Mixin 主要是用來和輔助的類型共享方法的,
+// 這樣單一繼承就不會影響程式碼重覆使用。
+// Mixin 宣告在類型定義的 "with" 後面。
+class Example23A {}
+class Example23Utils {
+ addTwo(n1, n2) {
+ return n1 + n2;
+ }
+}
+class Example23B extends Example23A with Example23Utils {
+ addThree(n1, n2, n3) {
+ return addTwo(n1, n2) + n3;
+ }
+}
+example23() {
+ var o = new Example23B(), r1 = o.addThree(1, 2, 3),
+ r2 = o.addTwo(1, 2);
+ print("Example23 addThree(1, 2, 3) results in '${r1}'");
+ print("Example23 addTwo(1, 2) results in '${r2}'");
+}
+
+// 類型的建構子和類型名相同,形式為
+// SomeClass() : super() {}, 其中 ": super()" 的部分是可選的,
+// 它用來傳遞參數給父類型的建構子。
+class Example24A {
+ var _value;
+ Example24A({value: "someValue"}) {
+ _value = value;
+ }
+ get value => _value;
+}
+class Example24B extends Example24A {
+ Example24B({value: "someOtherValue"}) : super(value: value);
+}
+example24() {
+ var o1 = new Example24B(),
+ o2 = new Example24B(value: "evenMore");
+ print("Example24 calling super during constructor '${o1.value}'");
+ print("Example24 calling super during constructor '${o2.value}'");
+}
+
+// 對於簡單的類型,有一種設置構造函數參數的快捷方式。
+// 只需要使用 this.parameterName 的前綴,
+// 它就會把參數設置為同名的實例變數。
+class Example25 {
+ var value, anotherValue;
+ Example25({this.value, this.anotherValue});
+}
+example25() {
+ var o = new Example25(value: "a", anotherValue: "b");
+ print("Example25 shortcut for constructor '${o.value}' and "
+ "'${o.anotherValue}'");
+}
+
+// 可以在大括號 {} 中宣告命名參數。
+// 大括號 {} 中宣告的參數的順序是隨意的。
+// 在中括號 [] 中宣告的參數也是可選的。
+example26() {
+ var _name, _surname, _email;
+ setConfig1({name, surname}) {
+ _name = name;
+ _surname = surname;
+ }
+ setConfig2(name, [surname, email]) {
+ _name = name;
+ _surname = surname;
+ _email = email;
+ }
+ setConfig1(surname: "Doe", name: "John");
+ print("Example26 name '${_name}', surname '${_surname}', "
+ "email '${_email}'");
+ setConfig2("Mary", "Jane");
+ print("Example26 name '${_name}', surname '${_surname}', "
+ "email '${_email}'");
+}
+
+// 使用 final 宣告的變數只能被設置一次。
+// 在類型裡面,final 實例變數可以通過常數的建構子參數設置。
+class Example27 {
+ final color1, color2;
+ // 更靈活一點的方法是在冒號 : 後面設置 final 實例變數。
+ Example27({this.color1, color2}) : color2 = color2;
+}
+example27() {
+ final color = "orange", o = new Example27(color1: "lilac", color2: "white");
+ print("Example27 color is '${color}'");
+ print("Example27 color is '${o.color1}' and '${o.color2}'");
+}
+
+// 要導入一個函式庫,使用 import "libraryPath" 的形式,或者如果要導入的是
+// 核心庫使用 import "dart:libraryName" 。還有一個稱為 "pub" 的套件管理工具,
+// 它使用 import "package:packageName" 的約定形式。
+// 看下這個文件頂部的 import "dart:collection"; 語法。
+// 導入語句必需在其它程式碼宣告之前出現。 IterableBase 來自於 dart:collection 。
+class Example28 extends IterableBase {
+ var names;
+ Example28() {
+ names = ["a", "b"];
+ }
+ get iterator => names.iterator;
+}
+example28() {
+ var o = new Example28();
+ o.forEach((name) => print("Example28 '${name}'"));
+}
+
+// 對於控制流程,我們有:
+// * 必需帶 break 的標準 switch 語法
+// * if-else 和三元運算子 ..?..:..
+// * 閉包和匿名函數
+// * break, continue 和 return 語法
+example29() {
+ var v = true ? 30 : 60;
+ switch (v) {
+ case 30:
+ print("Example29 switch statement");
+ break;
+ }
+ if (v < 30) {
+ } else if (v > 30) {
+ } else {
+ print("Example29 if-else statement");
+ }
+ callItForMe(fn()) {
+ return fn();
+ }
+ rand() {
+ v = new DM.Random().nextInt(50);
+ return v;
+ }
+ while (true) {
+ print("Example29 callItForMe(rand) '${callItForMe(rand)}'");
+ if (v != 30) {
+ break;
+ } else {
+ continue;
+ }
+ // 不會到這裡。
+ }
+}
+
+// 解析 int,把 double 轉成 int,或者使用 ~/ 運算符號在除法計算時僅保留整數位。
+// 讓我們也來場猜數遊戲吧。
+example30() {
+ var gn,
+ tooHigh = false,
+ n,
+ n2 = (2.0).toInt(),
+ top = int.parse("123") ~/ n2,
+ bottom = 0;
+ top = top ~/ 6;
+ gn = new DM.Random().nextInt(top + 1); // +1 because nextInt top is exclusive
+ print("Example30 Guess a number between 0 and ${top}");
+ guessNumber(i) {
+ if (n == gn) {
+ print("Example30 Guessed right! The number is ${gn}");
+ } else {
+ tooHigh = n > gn;
+ print("Example30 Number ${n} is too "
+ "${tooHigh ? 'high' : 'low'}. Try again");
+ }
+ return n == gn;
+ }
+
+ n = (top - bottom) ~/ 2;
+ while (!guessNumber(n)) {
+ if (tooHigh) {
+ top = n - 1;
+ } else {
+ bottom = n + 1;
+ }
+ n = bottom + ((top - bottom) ~/ 2);
+ }
+}
+
+// 選填位置參數:
+// 參數定義使用方括號 [ ],傳入參數是選填的。
+example31() {
+ findVolume31(int length, int breath, [int height]) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume31(10,20,30); // 可執行
+ findVolume31(10,20); // 也可執行
+}
+
+// 選填命名參數:
+// 參數定義使用大括號 { }, 傳入參數是選填的。
+// 必須傳入參數名稱及參數值,並以 : 分隔
+// 大括號的順序沒有差別
+// 這種類型參數可以幫我們避免多個參數傳入時造成混淆。
+example32() {
+ findVolume32(int length, int breath, {int height}) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume32(10,20,height:30); // 可執行 & 參數名稱在這邊有傳入
+ findVolume32(10,20); // 也可執行
+}
+
+// 選填預設參數:
+// 與選填命名參數相同,此外,我們為此參數定義的預設值
+// 如果沒有傳入值,就使用預設值
+example33() {
+ findVolume33(int length, int breath, {int height=10}) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume33(10,20,height:30); // 可執行
+ findVolume33(10,20); // 可執行
+}
+
+// 程式的唯一入口點是 main 函式。
+// 在程式開始執行 main 函式之前,不會執行任何外部程式碼。
+// 這樣有助於更快加載甚至是延遲加載程式啟動時所需要的部分;
+main() {
+ print("Learn Dart in 15 minutes!");
+ [
+ example1, example2, example3, example4, example5,
+ example6, example7, example8, example9, example10,
+ example11, example12, example13, example14, example15,
+ example16, example17, example18, example19, example20,
+ example21, example22, example23, example24, example25,
+ example26, example27, example28, example29,
+ example30 // 增加此註解可阻止dart formatter把所有項目都換行
+ ].forEach((ef) => ef());
+}
+
+```
+
+## 延伸閱讀
+
+Dart 有一個綜合性網站。它涵蓋了 API 參考、入門教學、文章以及更多,
+還包括一個有用的線上試用 Dart 頁面。
+* [https://www.dartlang.org](https://www.dartlang.org)
+* [https://try.dartlang.org](https://try.dartlang.org)
diff --git a/zh-tw/elixir-tw.html.markdown b/zh-tw/elixir-tw.html.markdown
index c15f90c1..3dba95b3 100644
--- a/zh-tw/elixir-tw.html.markdown
+++ b/zh-tw/elixir-tw.html.markdown
@@ -1,5 +1,5 @@
---
-language: elixir
+language: Elixir
contributors:
- ["Joao Marques", "http://github.com/mrshankly"]
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
@@ -19,10 +19,10 @@ Elixir 是一門建構在 Erlang 虛擬機上的現代函數式語言。它完
# 沒有多行註解的功能
# 但你可以連續使用多個單行
-# 用 `iex` 來進入 elixir shell
+# 用 `iex` 來進入 Elixir shell
# 用 `elixirc` 來編譯你的模組
-# 如果你已成功安裝 elixir 的話,這兩個命令應已在你的 path 下。
+# 如果你已成功安裝 Elixir 的話,這兩個命令應已在你的 path 下。
## ---------------------------
## -- 基本型別
@@ -50,7 +50,7 @@ elem({1, 2, 3}, 0) #=> 1
head #=> 1
tail #=> [2,3]
-# 在 elixir 中,就如同 Erlang 裡一樣,`=` 代表的是模式比對,而非指派。
+# 在 Elixir 中,就如同 Erlang 裡一樣,`=` 代表的是模式比對,而非指派。
#
# 這代表將使用左手邊的模式 (pattern) 去與右手邊的值進行比對。
#
@@ -80,7 +80,7 @@ string.
<<?a, ?b, ?c>> #=> "abc"
[?a, ?b, ?c] #=> 'abc'
-# `?a` 在 elixir 中會回傳字母 `a` 的 ASCII 整數
+# `?a` 在 Elixir 中會回傳字母 `a` 的 ASCII 整數
?a #=> 97
# 用 `++` 來合併串列,而合併二進位則要用 `<>`
@@ -105,7 +105,7 @@ lower..upper = 1..10 # 可以對 range 進行模式比對
5 * 2 #=> 10
10 / 2 #=> 5.0
-# 在 elixir 中, `/` 運算元永遠回傳浮點數。
+# 在 Elixir 中, `/` 運算元永遠回傳浮點數。
# 若需要回傳整數的除法,用 `div`
div(10, 2) #=> 5
@@ -290,7 +290,7 @@ Geometry.area({:circle, 3}) #=> 28.25999999999999801048
# Geometry.area({:circle, "not_a_number"})
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
-# 由於不可變特性 (immutability),遞迴在 elixir 中扮演重要的角色。
+# 由於不可變特性 (immutability),遞迴在 Elixir 中扮演重要的角色。
defmodule Recursion do
def sum_list([head | tail], acc) do
sum_list(tail, acc + head)
@@ -356,7 +356,7 @@ end
## -- 平行處理
## ---------------------------
-# Elixir 依靠 actor 模式來進行平行處理。在 elixir 中要寫出平行處理程式,
+# Elixir 依靠 actor 模式來進行平行處理。在 Elixir 中要寫出平行處理程式,
# 只需要三個基本要素:建立行程,發送訊息及接收訊息。
# 我們用 `spawn` 函式來建立行程,它接收一個函式當參數。
diff --git a/zh-tw/perl-tw.html.markdown b/zh-tw/perl-tw.html.markdown
new file mode 100644
index 00000000..55876e2a
--- /dev/null
+++ b/zh-tw/perl-tw.html.markdown
@@ -0,0 +1,328 @@
+---
+name: perl
+category: language
+language: perl
+filename: learnperl-tw.pl
+contributors:
+ - ["Korjavin Ivan", "http://github.com/korjavin"]
+ - ["Dan Book", "http://github.com/Grinnz"]
+translators:
+ - ["Kang-min Liu", "https://gugod.org"]
+ - ["Shih-Kai Chiu", "https://twitter.com/zard1989"]
+lang: zh-tw
+---
+
+Perl 5 是一款強大且功能豐富的程式語言,已經持續發展超過 25 年。
+
+從大型主機到行動裝置,Perl 5 能在上百種平台執行,適合快速打造產品原型,也適合大
+型專案開發。
+
+```perl
+# 註解列皆以井字號為開頭
+
+#### 嚴謹度
+
+use strict;
+use warnings;
+
+# 所有的 perl 程式檔案都應當包含此兩列程式碼。在如變數名稱有拼寫錯誤之時,
+# strict 能使編譯過程失敗。而對於像是將未定義值接到字串中等等易犯之錯誤,
+# warnings 則能提供適當的警告訊息。
+
+#### Perl 變數與其型別
+
+# 變數的開頭皆為一印記(sigil),是為一符號,用以標示其型別。
+# 變數名稱唯有以字母或底線開頭,後接字母、數字、底線若干,方為有效。
+
+### 在 Perl 語言中,主要的變數型別有三種:$純量、@陣列、%雜湊。
+
+## 純量
+# 一個純量變數,只能裝一個值:
+my $animal = "camel";
+my $answer = 42;
+my $display = "You have $answer ${animal}s.\n";
+
+# 純量值可為字串、整數、浮點數。Perl 會自動地在需要之時進行轉換。
+
+# 以單引號括住的字串內容與其字面之值完全相同。而以雙引號括住的字串,
+# 其中則能內插變數與像是這種表示換列字符 "\n" 的控制碼。
+
+## 陣列
+# 一個陣列,可以裝下很多值:
+my @animals = ("camel", "llama", "owl");
+my @numbers = (23, 42, 69);
+my @mixed = ("camel", 42, 1.23);
+
+# 陣列元素的存取,需要角括號。前方的印記為 $ 符號,表示只取一個值。
+my $second = $animals[1];
+
+# 欲知陣列之大小,在純量語境之下使用陣列便可。例如,將陣列裝到一個純量變數中。
+# 又或者是使用 "scalar" 算符。
+
+my $num_animals = @animals;
+print "Number of numbers: ", scalar(@numbers), "\n";
+
+# 陣列也能夠被安插在雙引號字串之內。各內容元素間隔,預設是一個空白字符。
+
+print "We have these numbers: @numbers\n";
+
+# 雙引號字串中,若有像電子郵件地址的部分,會被視為是在內插某個陣列的內容物。
+# 請稍加留意。
+
+my @example = ('secret', 'array');
+my $oops_email = "foo@example.com"; # 'foosecret array.com'
+my $ok_email = 'foo@example.com';
+
+## 雜湊
+# 一個雜湊,能裝下許多對的鍵與值:
+
+my %fruit_color = ("apple", "red", "banana", "yellow");
+
+# 善用空白與 "=>" 算符,就能將其排得得好看一些:
+
+my %fruit_color = (
+ apple => "red",
+ banana => "yellow",
+);
+
+# 雜湊元素的存取,需要大括號。前方的印記仍為 $ 符號,表示只取一個值。
+my $color = $fruit_color{apple};
+
+# 以 "keys" 與 "values" 兩個函數,則可一次取得雜湊中的所有鍵、所有值。
+my @fruits = keys %fruit_color;
+my @colors = values %fruit_color;
+
+# 關於純量、陣列、雜湊,在 perldata 文件之中,有更完整的描述。
+# (perldoc perldata)
+
+#### 參照
+
+# 以參照能組出結構更為複雜的資料型別。
+# 像是在陣列中放入雜湊、或是在雜湊裡放入陣列的雜湊。
+
+my $array_ref = \@array;
+my $hash_ref = \%hash;
+my @array_of_arrays = (\@array1, \@array2, \@array3);
+
+# 匿名陣列與匿名雜湊也是參照
+
+my $fruits = ["apple", "banana"];
+my $colors = {apple => "red", banana => "yellow"};
+
+# 在參照之前補上適當的印記,是為解參照。
+
+my @fruits_array = @$fruits;
+my %colors_hash = %$colors;
+
+# 以箭頭算符,便可在解參照同時存取其中一值。
+
+my $first = $array_ref->[0];
+my $value = $hash_ref->{banana};
+
+# 欲深入了解參照,詳見 perlreftut 與 perlref 兩份文件
+
+#### 條件結構與迴圈結構
+
+# Perl 語言中亦具備常見的條件結講與迴圈結構。
+
+if ($var) {
+ ...
+} elsif ($var eq 'bar') {
+ ...
+} else {
+ ...
+}
+
+unless (condition) {
+ ...
+}
+# 這算是可讀性較好的 "if (!condition)"
+
+# 倒裝句型算是某「很 Perl 的」寫法
+print "Yow!" if $zippy;
+print "We have no bananas" unless $bananas;
+
+# while
+while (condition) {
+ ...
+}
+
+my $max = 5;
+# 以 for 迴圈,$i 為迭代變數
+for my $i (0 .. $max) {
+ print "index is $i";
+}
+
+for my $element (@elements) {
+ print $element;
+}
+
+map {print} @elements;
+
+# 迭代變數為 $_
+for (@elements) {
+ print;
+}
+
+# 對雜湊進行迭代(for 與 foreach 完全相同)
+
+foreach my $key (keys %hash) {
+ print $key, ': ', $hash{$key}, "\n";
+}
+
+# 又是「很 Perl 的」倒裝句法
+print for @elements;
+
+# 對一雜湊參照之中迭代,逐一走過其鍵與值
+print $hash_ref->{$_} for keys %$hash_ref;
+
+#### 正規表示式
+
+# Perl 中,對正規表示式的支援既廣亦深,在 perlrequick、perlretut 等各處文件中
+# 都有更加完整的文件。不過,簡而言之:
+
+# 簡易比對
+if (/foo/) { ... } # 若 $_ 內含 "foo" 則為真
+if ($x =~ /foo/) { ... } # 若 $x 內含 "foo" 則為真
+
+# 簡易取代
+$x =~ s/foo/bar/; # 將 $x 中第一個出現的 foo 換為 bar
+$x =~ s/foo/bar/g; # 將 $x 中所有出現的 foo 換為 bar
+
+#### 檔案與輸出入
+
+# 以 "open" 函式開檔後,便可自檔案輸入或對其輸出
+
+# 讀檔:
+open(my $in, "<", "input.txt") or die "Can't open input.txt: $!";
+
+# 寫檔(若檔案已經存在,舊內容會被清空):
+open(my $out, ">", "output.txt") or die "Can't open output.txt: $!";
+
+# 寫檔(若檔案已經存在,會寫到檔尾去):
+open(my $log, ">>", "my.log") or die "Can't open my.log: $!";
+
+# 使用 "<>" 算符,能對檔案代號進行讀取。在純量語境下,會自檔案代號讀一列內容。
+# 而在串列語境下,對讀入整個檔案。每一列都會成為串列中一項元素。
+
+my $line = <$in>;
+my @lines = <$in>;
+
+# 以 "print" 函式,則可對檔案代號進行輸出。
+
+print $out @lines;
+print $log $msg, "\n";
+
+#### 函式之撰寫
+
+# 撰寫函式很是容易:
+
+sub logger {
+ my $logmessage = shift;
+
+ open my $logfile, ">>", "my.log" or die "Could not open my.log: $!";
+
+ print $logfile $logmessage;
+}
+
+# 之後,使用起來就與內建函式無異:
+
+logger("We have a logger subroutine!");
+
+#### 模組
+
+# 所謂模組,就是一組 Perl 程式碼,由一些函式組成,並可讓其他 Perl 程式碼來利用。
+# 為了讓 perl 能找至,通常模組之副檔名 .pm 。
+
+package MyModule;
+use strict;
+use warnings;
+
+sub trim {
+ my $string = shift;
+ $string =~ s/^\s+//;
+ $string =~ s/\s+$//;
+ return $string;
+}
+
+1;
+
+# 自他處利用:
+
+use MyModule;
+MyModule::trim($string);
+
+# Exporter 模組能將函式出口,好讓它們能被這樣利用:
+
+use MyModule 'trim';
+trim($string);
+
+# 有許多 Perl 模組能從 CPAN (https://www.cpan.org) 下載下來,各式各樣的機能讓你
+# 能免於重新發明輪子。不少高人氣模組,如 Exporter,則是與 Perl 一同釋出、散佈。
+# 更多關於 Perl 模組的細節,詳見 perlmod 文件。
+
+#### 物件
+
+# Perl 中的物件,只是個參照,但同時又知道自己屬於哪個類別(package),於是對自身
+# 調用方法(函式)時方知去何處尋找函式本體。在建構子(通常是 "new")中,都是以
+# "bless" 函式來標記參照與其類別。只不過,若你使用像 Moose 或 Moo 模組的話,這些
+# 都不必自己來(總之請繼續往下讀)。
+
+package MyCounter;
+use strict;
+use warnings;
+
+sub new {
+ my $class = shift;
+ my $self = {count => 0};
+ return bless $self, $class;
+}
+
+sub count {
+ my $self = shift;
+ return $self->{count};
+}
+
+sub increment {
+ my $self = shift;
+ $self->{count}++;
+}
+
+1;
+
+# 以箭頭運算符,便可對某類別或某物件呼叫某方法:
+use MyCounter;
+my $counter = MyCounter->new;
+print $counter->count, "\n"; # 0
+$counter->increment;
+print $counter->count, "\n"; # 1
+
+# CPAN 上的 Moose 與 Moo 模組能助你撰寫類別本體。它們提供了建構子,與簡單易懂的
+# 語法能來宣告屬性。前述的類別改寫之後,如下:
+
+package MyCounter;
+use Moo; # 同時也啟用 strict 與 warnings
+
+has 'count' => (is => 'rwp', default => 0, init_arg => undef);
+
+sub increment {
+ my $self = shift;
+ $self->_set_count($self->count + 1);
+}
+
+1;
+
+# 物件導向程式設計於 perlootut 文件中有詳盡的說明。
+# 此外,perlobj 文件中更涵蓋了底層實做之細節。
+```
+
+#### 常見問答集
+
+perlfaq 是問與答,涵蓋許多常見問題和解法,常常對該用哪些 CPAN 模組有很好的建議。
+
+#### 延伸閱讀
+
+ - [perl-tutorial](http://perl-tutorial.org/)
+ - [Learn Perl](https://www.perl.org/learn.html)
+ - [perldoc](http://perldoc.perl.org/)
+ - 內建函式 : `perldoc perlintro`
diff --git a/zh-tw/python-tw.html.markdown b/zh-tw/pythonlegacy-tw.html.markdown
index cd7481d7..575897e2 100644
--- a/zh-tw/python-tw.html.markdown
+++ b/zh-tw/pythonlegacy-tw.html.markdown
@@ -1,5 +1,5 @@
---
-language: python
+language: Python 2 (legacy)
contributors:
- ["Louie Dinh", "http://ldinh.ca"]
- ["Amin Bandali", "http://aminbandali.com"]
@@ -7,7 +7,7 @@ contributors:
- ["evuez", "http://github.com/evuez"]
translators:
- ["Michael Yeh", "https://hinet60613.github.io/"]
-filename: learnpython-tw.py
+filename: learnpythonlegacy-tw.py
lang: zh-tw
---
@@ -16,7 +16,7 @@ Python是在1990年代早期由Guido Van Rossum創建的。它是現在最流行
非常歡迎各位給我們任何回饋! 你可以在[@louiedinh](http://twitter.com/louiedinh) 或 louiedinh [at] [google's email service]聯絡到我。
註: 本篇文章適用的版本為Python 2.7,但大部分的Python 2.X版本應該都適用。 Python 2.7將會在2020年停止維護,因此建議您可以從Python 3開始學Python。
-Python 3.X可以看這篇[Python 3 教學 (英文)](http://learnxinyminutes.com/docs/python3/).
+Python 3.X可以看這篇[Python 3 教學 (英文)](http://learnxinyminutes.com/docs/python/).
讓程式碼同時支援Python 2.7和3.X是可以做到的,只要引入
[`__future__` imports](https://docs.python.org/2/library/__future__.html) 模組.