diff options
Diffstat (limited to 'zh-cn')
-rw-r--r-- | zh-cn/bf-cn.html.markdown (renamed from zh-cn/brainfuck-cn.html.markdown) | 2 | ||||
-rw-r--r-- | zh-cn/common-lisp-cn.html.markdown | 2 | ||||
-rw-r--r-- | zh-cn/haskell-cn.html.markdown | 6 | ||||
-rw-r--r-- | zh-cn/java-cn.html.markdown | 6 | ||||
-rw-r--r-- | zh-cn/kotlin-cn.html.markdown | 346 | ||||
-rw-r--r-- | zh-cn/lua-cn.html.markdown | 31 | ||||
-rw-r--r-- | zh-cn/markdown-cn.html.markdown | 8 | ||||
-rw-r--r-- | zh-cn/python3-cn.html.markdown | 2 | ||||
-rw-r--r-- | zh-cn/r-cn.html.markdown | 2 | ||||
-rw-r--r-- | zh-cn/scala-cn.html.markdown | 2 | ||||
-rw-r--r-- | zh-cn/swift-cn.html.markdown | 172 | ||||
-rw-r--r-- | zh-cn/tmux-cn.html.markdown | 253 | ||||
-rw-r--r-- | zh-cn/typescript-cn.html.markdown | 173 | ||||
-rw-r--r-- | zh-cn/zfs-cn.html.markdown | 397 |
14 files changed, 1299 insertions, 103 deletions
diff --git a/zh-cn/brainfuck-cn.html.markdown b/zh-cn/bf-cn.html.markdown index a6f3fa09..6cea3012 100644 --- a/zh-cn/brainfuck-cn.html.markdown +++ b/zh-cn/bf-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: brainfuck +language: bf lang: zh-cn contributors: - ["Prajit Ramachandran", "http://prajitr.github.io/"] diff --git a/zh-cn/common-lisp-cn.html.markdown b/zh-cn/common-lisp-cn.html.markdown index b82829a9..c7fe7e2c 100644 --- a/zh-cn/common-lisp-cn.html.markdown +++ b/zh-cn/common-lisp-cn.html.markdown @@ -14,6 +14,8 @@ ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范 免费的经典的入门书籍[《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) +许多人都抱怨上面这本书的翻译。[《ANSI Common Lisp》](http://acl.readthedocs.org/en/latest/)也许对中文读者更友好一些。 + 另外还有一本热门的近期出版的 [Land of Lisp](http://landoflisp.com/). diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown index 8904970f..b0b1183f 100644 --- a/zh-cn/haskell-cn.html.markdown +++ b/zh-cn/haskell-cn.html.markdown @@ -200,13 +200,13 @@ foo 5 -- 75 -- 你可以使用 `$` 来移除多余的括号。 -- 修改前 -(even (fib 7)) -- true +(even (fib 7)) -- False -- 修改后 -even . fib $ 7 -- true +even . fib $ 7 -- False -- 等价地 -even $ fib 7 -- true +even $ fib 7 -- False ---------------------------------------------------- -- 5. 类型声明 diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown index 12afa59a..1e9c38f6 100644 --- a/zh-cn/java-cn.html.markdown +++ b/zh-cn/java-cn.html.markdown @@ -302,7 +302,7 @@ class Bicycle { // 构造函数是初始化一个对象的方式 // 以下是一个默认构造函数 - public Bi450635425cycle() { + public Bicycle() { gear = 1; cadence = 50; speed = 5; @@ -328,7 +328,7 @@ class Bicycle { return cadence; } - // void返450635425回值函数没有返回值 + // void返回值函数没有返回值 public void setCadence(int newValue) { cadence = newValue; } @@ -405,4 +405,4 @@ class PennyFarthing extends Bicycle { * [泛型](http://docs.oracle.com/javase/tutorial/java/generics/index.html) -* [Java代码规范](http://www.oracle.com/technetwork/java/codeconv-138413.html) +* [Java代码规范](http://www.oracle.com/technetwork/java/codeconvtoc-136057.html) diff --git a/zh-cn/kotlin-cn.html.markdown b/zh-cn/kotlin-cn.html.markdown new file mode 100644 index 00000000..1fd12f5b --- /dev/null +++ b/zh-cn/kotlin-cn.html.markdown @@ -0,0 +1,346 @@ +--- +language: kotlin +contributors: + - ["S Webber", "https://github.com/s-webber"] +translators: + - ["Jimin Lu", "https://github.com/lujimin"] +filename: LearnKotlin-cn.kt +lang: zh-cn +--- + +Kotlin是一门适用于JVM、Android和浏览器的静态类型编程语言。它100%兼容Java。 +[了解更多。](https://kotlinlang.org/) + +```java +// 单行注释从 // 开始 +/* +多行注释看起来像这样。 +*/ + +// "package" 关键字的工作方式与Java相同。 +package com.learnxinyminutes.kotlin + +/* +Kotlin程序的入口点是一个"main"函数 +该函数传递一个包含任何命令行参数的数组。 +*/ +fun main(args: Array<String>) { + /* + 使用"var"或"val"来声明一个值。 + "val"声明的值不能被重新赋值,而"var"声明的值可以。 + */ + val fooVal = 10 // 以后我们不能再次给fooVal赋值 + var fooVar = 10 + fooVar = 20 // fooVar可以被再次赋值 + + /* + 在大多数情况下,Kotlin可以确定变量的类型是什么, + 所以我们不必要每次都去明确指定它。 + 我们可以像这样明确地声明一个变量的类型: + */ + val foo : Int = 7 + + /* + 可以采取和Java类似的方法来表示一个字符串。 + 用反斜杠来转义字符。 + */ + val fooString = "My String Is Here!"; + val barString = "Printing on a new line?\nNo Problem!"; + val bazString = "Do you want to add a tab?\tNo Problem!"; + println(fooString); + println(barString); + println(bazString); + + /* + 原始字符串用三重引号(""")来定义。 + 原始字符串可以包含换行符以及其他任何字符。 + */ + val fooRawString = """ +fun helloWorld(val name : String) { + println("Hello, world!") +} +""" + println(fooRawString) + + /* + 字符串可以包含模板表达式。 + 模板表达式从一个美元符号($)开始。 + */ + val fooTemplateString = "$fooString has ${fooString.length} characters" + println(fooTemplateString) + + /* + 当某个变量的值可以为 null 的时候,我们必须被明确指定它是可为空的。 + 在变量声明处的类型后面加上?来标识它是可为空的。 + 我们可以用?.操作符来访问可为空的变量。 + 我们可以用?:操作符来指定一个在变量为空时使用的替代值。 + */ + var fooNullable: String? = "abc" + println(fooNullable?.length) // => 3 + println(fooNullable?.length ?: -1) // => 3 + fooNullable = null + println(fooNullable?.length) // => null + println(fooNullable?.length ?: -1) // => -1 + + /* + 使用"fun"关键字来声明一个函数。 + 函数的参数在函数名后面的括号内指定。 + 函数的参数可以设定一个默认值。 + 如果需要的话,函数的返回值类型可以在参数后面指定。 + */ + fun hello(name: String = "world") : String { + return "Hello, $name!" + } + println(hello("foo")) // => Hello, foo! + println(hello(name = "bar")) // => Hello, bar! + println(hello()) // => Hello, world! + + /* + 用"vararg"关键字来修饰一个函数的参数来允许可变参数传递给该函数 + */ + fun varargExample(vararg names: Int) { + println("Argument has ${names.size} elements") + } + varargExample() // => Argument has 0 elements + varargExample(1) // => Argument has 1 elements + varargExample(1, 2, 3) // => Argument has 3 elements + + /* + 当函数只包含一个单独的表达式时,大括号可以被省略。 + 函数体可以被指定在一个=符号后面。 + */ + fun odd(x: Int): Boolean = x % 2 == 1 + println(odd(6)) // => false + println(odd(7)) // => true + + // 如果返回值类型可以被推断,那么我们不需要指定它。 + fun even(x: Int) = x % 2 == 0 + println(even(6)) // => true + println(even(7)) // => false + + // 函数可以用函数作为参数并且可以返回函数。 + fun not(f: (Int) -> Boolean) : (Int) -> Boolean { + return {n -> !f.invoke(n)} + } + // 命名函数可以用::运算符被指定为参数。 + val notOdd = not(::odd) + val notEven = not(::even) + // 匿名函数可以被指定为参数。 + val notZero = not {n -> n == 0} + /* + 如果一个匿名函数只有一个参数 + 那么它的声明可以被省略(连同->)。 + 这个参数的名字是"it"。 + */ + val notPositive = not {it > 0} + for (i in 0..4) { + println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}") + } + + // "class"关键字用来声明类。 + class ExampleClass(val x: Int) { + fun memberFunction(y: Int) : Int { + return x + y + } + + infix fun infixMemberFunction(y: Int) : Int { + return x * y + } + } + /* + 我们调用构造方法来创建一个新的实例。 + 注意,Kotlin没有"new"关键字。 + */ + val fooExampleClass = ExampleClass(7) + // 可以使用一个点号来调用成员函数。 + println(fooExampleClass.memberFunction(4)) // => 11 + /* + 如果使用"infix"关键字来标记一个函数 + 那么可以使用中缀表示法来调用该函数。 + */ + println(fooExampleClass infixMemberFunction 4) // => 28 + + /* + 数据类是创建只包含数据的类的一个简洁的方法。 + "hashCode"、"equals"和"toString"方法将被自动生成。 + */ + data class DataClassExample (val x: Int, val y: Int, val z: Int) + val fooData = DataClassExample(1, 2, 4) + println(fooData) // => DataClassExample(x=1, y=2, z=4) + + // 数据类有一个"copy"函数 + val fooCopy = fooData.copy(y = 100) + println(fooCopy) // => DataClassExample(x=1, y=100, z=4) + + // 对象可以被解构成为多个变量 + val (a, b, c) = fooCopy + println("$a $b $c") // => 1 100 4 + + // "with"函数类似于JavaScript中的"with"用法。 + data class MutableDataClassExample (var x: Int, var y: Int, var z: Int) + val fooMutableDate = MutableDataClassExample(7, 4, 9) + with (fooMutableDate) { + x -= 2 + y += 2 + z-- + } + println(fooMutableDate) // => MutableDataClassExample(x=5, y=6, z=8) + + /* + 我们可以使用"listOf"函数来创建一个list。 + 这个list是不可变的 - 元素不可以被添加或删除。 + */ + val fooList = listOf("a", "b", "c") + println(fooList.size) // => 3 + println(fooList.first()) // => a + println(fooList.last()) // => c + // 可以通过索引来访问list中的元素。 + println(fooList[1]) // => b + + // 可以使用"mutableListOf"函数来创建一个可变的list。 + val fooMutableList = mutableListOf("a", "b", "c") + fooMutableList.add("d") + println(fooMutableList.last()) // => d + println(fooMutableList.size) // => 4 + + // 我们可以使用"setOf"函数来创建一个set。 + val fooSet = setOf("a", "b", "c") + println(fooSet.contains("a")) // => true + println(fooSet.contains("z")) // => false + + // 我们可以使用"mapOf"函数来创建一个map。 + val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9) + // 可以通过键来访问map中的值。 + println(fooMap["a"]) // => 8 + + /* + 序列表示惰性求值集合。 + 我们可以使用"generateSequence"函数来创建一个序列。 + */ + val fooSequence = generateSequence(1, {it + 1}) + val x = fooSequence.take(10).toList() + println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + // 一个用序列来生成斐波那契数列的例子。 + fun fibonacciSequence() : Sequence<Long> { + var a = 0L + var b = 1L + + fun next() : Long { + val result = a + b + a = b + b = result + return a + } + + return generateSequence(::next) + } + val y = fibonacciSequence().take(10).toList() + println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + + // Kotlin为集合提供高阶函数。 + val z = (1..9).map {it * 3} + .filter {it < 20} + .groupBy {it % 2 == 0} + .mapKeys {if (it.key) "even" else "odd"} + println(z) // => {odd=[3, 9, 15], even=[6, 12, 18]} + + // 任何提供迭代器的都可以使用"for"循环。 + for (c in "hello") { + println(c) + } + + // "while"循环的用法和其他语言一样。 + var ctr = 0 + while (ctr < 5) { + println(ctr) + ctr++ + } + do { + println(ctr) + ctr++ + } while (ctr < 10) + + // "when"可以用来替代"if-else if"链。 + val i = 10 + when { + i < 7 -> println("first block") + fooString.startsWith("hello") -> println("second block") + else -> println("else block") + } + + // "when"可以带参数。 + when (i) { + 0, 21 -> println("0 or 21") + in 1..20 -> println("in the range 1 to 20") + else -> println("none of the above") + } + + // "when"可以作为一个函数,提供返回值。 + var result = when (i) { + 0, 21 -> "0 or 21" + in 1..20 -> "in the range 1 to 20" + else -> "none of the above" + } + println(result) + + /* + 我们可以通过使用"is"操作符来检查一个对象是否是某个类型的。 + 如果对象通过了类型检查那么它可以作为该类型使用而不需要强制转换它。 + */ + fun smartCastExample(x: Any) : Boolean { + if (x is Boolean) { + // x自动转换为Boolean + return x + } else if (x is Int) { + // x自动转换为Int + return x > 0 + } else if (x is String) { + // x自动转换为String + return x.isNotEmpty() + } else { + return false + } + } + println(smartCastExample("Hello, world!")) // => true + println(smartCastExample("")) // => false + println(smartCastExample(5)) // => true + println(smartCastExample(0)) // => false + println(smartCastExample(true)) // => true + + /* + 扩展是用来给一个类添加新的功能的。 + 它类似于C#的扩展方法。 + */ + fun String.remove(c: Char): String { + return this.filter {it != c} + } + println("Hello, world!".remove('l')) // => Heo, word! + + println(EnumExample.A) // => A + println(ObjectExample.hello()) // => hello +} + +// 枚举类和Java的枚举类型类似。 +enum class EnumExample { + A, B, C +} + +/* +"object"关键字用来创建单例对象。 +我们不能把它赋给一个变量,但我们可以通过它的名字引用它。 +这类似于Scala的单例对象。 +*/ +object ObjectExample { + fun hello() : String { + return "hello" + } +} + +``` + +### 进一步阅读 + +* [Kotlin教程](https://kotlinlang.org/docs/tutorials/) +* [在您的浏览器中使用Kotlin](http://try.kotlinlang.org/) +* [Kotlin资源列表](http://kotlin.link/) diff --git a/zh-cn/lua-cn.html.markdown b/zh-cn/lua-cn.html.markdown index 098d0ab5..6736dc2a 100644 --- a/zh-cn/lua-cn.html.markdown +++ b/zh-cn/lua-cn.html.markdown @@ -91,10 +91,10 @@ until num == 0 -- 2. 函数。 ---------------------------------------------------- -function fib(n) - if n < 2 then return 1 end - return fib(n - 2) + fib(n - 1) -end +function fib(n) + if n < 2 then return n end + return fib(n - 2) + fib(n - 1) +end -- 支持闭包及匿名函数: function adder(x) @@ -129,9 +129,11 @@ function f(x) return x * x end f = function (x) return x * x end -- 这些也是等价的: -local function g(x) return math.sin(x) end -local g; g = function (x) return math.sin(x) end --- 'local g'使得g可以自引用。 +local function g(x) return math.sin(x) end +local g; g = function (x) return math.sin(x) end +-- 以上均因'local g',使得g可以自引用。 +local g = function(x) return math.sin(x) end +-- 等价于 local function g(x)..., 但函数体中g不可自引用 -- 顺便提下,三角函数以弧度为单位。 @@ -210,7 +212,7 @@ f2 = {a = 2, b = 3} metafraction = {} function metafraction.__add(f1, f2) - sum = {} + local sum = {} sum.b = f1.b * f2.b sum.a = f1.a * f2.b + f2.a * f1.b return sum @@ -273,7 +275,7 @@ eatenBy = myFavs.animal -- 可以工作!感谢元表 Dog = {} -- 1. function Dog:new() -- 2. - newObj = {sound = 'woof'} -- 3. + local newObj = {sound = 'woof'} -- 3. self.__index = self -- 4. return setmetatable(newObj, self) -- 5. end @@ -307,7 +309,7 @@ mrDog:makeSound() -- 'I say woof' -- 8. LoudDog = Dog:new() -- 1. function LoudDog:makeSound() - s = self.sound .. ' ' -- 2. + local s = self.sound .. ' ' -- 2. print(s .. s .. s) end @@ -328,7 +330,7 @@ seymour:makeSound() -- 'woof woof woof' -- 4. -- 如果有必要,子类也可以有new(),与基类相似: function LoudDog:new() - newObj = {} + local newObj = {} -- 初始化newObj self.__index = self return setmetatable(newObj, self) @@ -340,7 +342,9 @@ end --[[ 我把这部分给注释了,这样脚本剩下的部分可以运行 +``` +```lua -- 假设文件mod.lua的内容类似这样: local M = {} @@ -411,4 +415,9 @@ lua-users.org上的[Lua简明参考](http://lua-users.org/files/wiki_insecure/us * <a href="http://lua-users.org/wiki/IoLibraryTutorial">io library</a> * <a href="http://lua-users.org/wiki/OsLibraryTutorial">os library</a> +顺便说一下,整个文件是可运行的Lua; +保存为 learn-cn.lua 用命令 `lua learn-cn.lua` 启动吧! + +本文首次撰写于 [tylerneylon.com](http://tylerneylon.com) 同时也有 [github gist](https://gist.github.com/tylerneylon/5853042) 版. + 使用Lua,欢乐常在! diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index b633714d..87ed46ad 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -53,7 +53,7 @@ __此文本也是__ **_或者这样。_** *__这个也是!__* -<!-- 在 Github 采用的 Markdown 中 --> +<!-- 在 GitHub 采用的 Markdown 中 --> ~~此文本为删除线效果。~~ @@ -142,7 +142,7 @@ __此文本也是__ John 甚至不知道 `go_to()` 方程是干嘛的! -<!-- 在Github的 Markdown中,对于代码你可以使用特殊的语法 --> +<!-- 在GitHub的 Markdown中,对于代码你可以使用特殊的语法 --> \`\`\`ruby <!-- 插入时记得移除反斜线, 仅留```ruby ! --> def foobar @@ -150,7 +150,7 @@ def foobar end \`\`\` <!-- 这里也是,移除反斜线,仅留 ``` --> -<!-- 以上代码不需要缩进,而且 Github 会根据```后表明的语言来进行语法高亮 --> +<!-- 以上代码不需要缩进,而且 GitHub 会根据```后表明的语言来进行语法高亮 --> <!-- 水平线 (<hr />) --> <!-- 水平线可由三个或以上的星号或者减号创建,可带可不带空格。 --> @@ -220,7 +220,7 @@ end 斜体化, 所以我就: \*这段置文字于星号之间\*。 <!-- 表格 --> -<!-- 表格只被 Github 的 Markdown 支持,并且有一点笨重,但如果你真的要用的话: --> +<!-- 表格只被 GitHub 的 Markdown 支持,并且有一点笨重,但如果你真的要用的话: --> | 第一列 | 第二列 | 第三列 | | :---------- | :------: | ----------: | diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index c223297c..76455a46 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -535,7 +535,7 @@ Human.grunt() # => "*grunt*" # 用import导入模块 import math -print(math.sqrt(16)) # => 4 +print(math.sqrt(16)) # => 4.0 # 也可以从模块中导入个别值 from math import ceil, floor diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown index 0c46bc22..55a29b11 100644 --- a/zh-cn/r-cn.html.markdown +++ b/zh-cn/r-cn.html.markdown @@ -285,7 +285,7 @@ while (a > 4) { } # 记住,在 R 语言中 for / while 循环都很慢 -# 建议使用 apply()(我们一会介绍)来错做一串数据(比如一列或者一行数据) +# 建议使用 apply()(我们一会介绍)来操作一串数据(比如一列或者一行数据) # IF/ELSE diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index 508dd58e..f3327b5b 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -369,7 +369,7 @@ object Dog { // Case 类是有额外内建功能的类。Scala 初学者常遇到的问题之一便是何时用类 // 和何时用 case 类。界线比较模糊,但通常类倾向于封装,多态和行为。类中的值 -// 的作用域一般为 private , 只有方向是暴露的。case 类的主要目的是放置不可变 +// 的作用域一般为 private , 只有方法是暴露的。case 类的主要目的是放置不可变 // 数据。它们通常只有几个方法,且方法几乎没有副作用。 case class Person(name: String, phoneNumber: String) diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index 28001e3f..017a7812 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -5,7 +5,8 @@ contributors: - ["Grant Timmerman", "http://github.com/grant"] translators: - ["Xavier Yao", "http://github.com/xavieryao"] - - ["Joey Huang", "http://github.com/kamidox"] + - ["Joey Huang", "http://github.com/kamidox"] + - ["CY Lim", "http://github.com/cylim"] lang: zh-cn --- @@ -13,13 +14,13 @@ Swift 是 Apple 开发的用于 iOS 和 OS X 开发的编程语言。Swift 于20 Swift 的官方语言教程 [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) 可以从 iBooks 免费下载. -亦可参阅:Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) ——一个完整的Swift 教程 +亦可参阅:Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/) ——一个完整的Swift 教程 ```swift // 导入外部模块 import UIKit -// +// // MARK: 基础 // @@ -28,12 +29,14 @@ import UIKit // TODO: TODO 标记 // FIXME: FIXME 标记 -println("Hello, world") +// Swift2.0 println() 及 print() 已经整合成 print()。 +print("Hello, world") // 这是原本的 println(),会自动进入下一行 +print("Hello, world", terminator: "") // 如果不要自动进入下一行,需设定结束符为空串 // 变量 (var) 的值设置后可以随意改变 // 常量 (let) 的值设置后不能改变 var myVariable = 42 -let øπΩ = "value" // 可以支持 unicode 变量名 +let øπΩ = "value" // 可以支持 unicode 变量名 let π = 3.1415926 let myConstant = 3.1415926 let explicitDouble: Double = 70 // 明确指定变量类型为 Double ,否则编译器将自动推断变量类型 @@ -46,16 +49,17 @@ let piText = "Pi = \(π), Pi 2 = \(π * 2)" // 格式化字符串 // 条件编译 // 使用 -D 定义编译开关 #if false - println("Not printed") + print("Not printed") let buildValue = 3 #else let buildValue = 7 #endif -println("Build value: \(buildValue)") // Build value: 7 +print("Build value: \(buildValue)") // Build value: 7 /* - Optionals 是 Swift 的新特性,它允许你存储两种状态的值给 Optional 变量:有效值或 None - + Optionals 是 Swift 的新特性,它允许你存储两种状态的值给 Optional 变量:有效值或 None 。 + 可在值名称后加个问号 (?) 来表示这个值是 Optional。 + Swift 要求所有的 Optinal 属性都必须有明确的值,如果为空,则必须明确设定为 nil Optional<T> 是个枚举类型 @@ -67,13 +71,17 @@ var someOptionalString2: Optional<String> = "optional" if someOptionalString != nil { // 变量不为空 if someOptionalString!.hasPrefix("opt") { - println("has the prefix") + print("has the prefix") } - + let empty = someOptionalString?.isEmpty } someOptionalString = nil +/* + 使用 (!) 可以解决无法访问optional值的运行错误。若要使用 (!)来强制解析,一定要确保 Optional 里不是 nil参数。 +*/ + // 显式解包 optional 变量 var unwrappedString: String! = "Value is expected." // 下面语句和上面完全等价,感叹号 (!) 是个后缀运算符,这也是个语法糖 @@ -94,7 +102,7 @@ anyObjectVar = "Changed value to a string, not good practice, but possible." /* 这里是注释 - + /* 支持嵌套的注释 */ @@ -116,6 +124,7 @@ shoppingList[1] = "bottle of water" let emptyArray = [String]() // 使用 let 定义常量,此时 emptyArray 数组不能添加或删除内容 let emptyArray2 = Array<String>() // 与上一语句等价,上一语句更常用 var emptyMutableArray = [String]() // 使用 var 定义变量,可以向 emptyMutableArray 添加数组元素 +var explicitEmptyMutableStringArray: [String] = [] // 与上一语句等价 // 字典 var occupations = [ @@ -126,6 +135,7 @@ occupations["Jayne"] = "Public Relations" // 修改字典,如果 key 不存 let emptyDictionary = [String: Float]() // 使用 let 定义字典常量,字典常量不能修改里面的值 let emptyDictionary2 = Dictionary<String, Float>() // 与上一语句类型等价,上一语句更常用 var emptyMutableDictionary = [String: Float]() // 使用 var 定义字典变量 +var explicitEmptyMutableDictionary: [String: Float] = [:] // 与上一语句类型等价 // @@ -136,21 +146,21 @@ var emptyMutableDictionary = [String: Float]() // 使用 var 定义字典变量 let myArray = [1, 1, 2, 3, 5] for value in myArray { if value == 1 { - println("One!") + print("One!") } else { - println("Not one!") + print("Not one!") } } // 字典的 for 循环 var dict = ["one": 1, "two": 2] for (key, value) in dict { - println("\(key): \(value)") + print("\(key): \(value)") } // 区间的 loop 循环:其中 `...` 表示闭环区间,即[-1, 3];`..<` 表示半开闭区间,即[-1,3) for i in -1...shoppingList.count { - println(i) + print(i) } shoppingList[1...2] = ["steak", "peacons"] // 可以使用 `..<` 来去掉最后一个元素 @@ -161,9 +171,9 @@ while i < 1000 { i *= 2 } -// do-while 循环 -do { - println("hello") +// repeat-while 循环 +repeat { + print("hello") } while 1 == 2 // Switch 语句 @@ -177,7 +187,7 @@ case "cucumber", "watercress": let vegetableComment = "That would make a good tea sandwich." case let localScopeValue where localScopeValue.hasSuffix("pepper"): let vegetableComment = "Is it a spicy \(localScopeValue)?" -default: // 在 Swift 里,switch 语句的 case 必须处理所有可能的情况,如果 case 无法全部处理,则必须包含 default语句 +default: // 在 Swift 里,switch 语句的 case 必须处理所有可能的情况,如果 case 无法全部处理,则必须包含 default语句 let vegetableComment = "Everything tastes good in soup." } @@ -202,11 +212,11 @@ default: // 在 Swift 里,switch 语句的 case 必须处理所有可能的情 func greet(name: String, day: String) -> String { return "Hello \(name), today is \(day)." } -greet("Bob", "Tuesday") +greet("Bob", day: "Tuesday") -// 函数参数前带 `#` 表示外部参数名和内部参数名使用同一个名称。 +// 第一个参数表示外部参数名和内部参数名使用同一个名称。 // 第二个参数表示外部参数名使用 `externalParamName` ,内部参数名使用 `localParamName` -func greet2(#requiredName: String, externalParamName localParamName: String) -> String { +func greet2(requiredName requiredName: String, externalParamName localParamName: String) -> String { return "Hello \(requiredName), the day is \(localParamName)" } greet2(requiredName:"John", externalParamName: "Sunday") // 调用时,使用命名参数来指定参数的值 @@ -219,14 +229,14 @@ let pricesTuple = getGasPrices() let price = pricesTuple.2 // 3.79 // 通过下划线 (_) 来忽略不关心的值 let (_, price1, _) = pricesTuple // price1 == 3.69 -println(price1 == pricesTuple.1) // true -println("Gas price: \(price)") +print(price1 == pricesTuple.1) // true +print("Gas price: \(price)") // 可变参数 func setup(numbers: Int...) { // 可变参数是个数组 - let number = numbers[0] - let argCount = numbers.count + let _ = numbers[0] + let _ = numbers.count } // 函数变量以及函数作为返回值返回 @@ -247,8 +257,8 @@ func swapTwoInts(inout a: Int, inout b: Int) { } var someIntA = 7 var someIntB = 3 -swapTwoInts(&someIntA, &someIntB) -println(someIntB) // 7 +swapTwoInts(&someIntA, b: &someIntB) +print(someIntB) // 7 // @@ -256,7 +266,7 @@ println(someIntB) // 7 // var numbers = [1, 2, 6] -// 函数是闭包的一个特例 +// 函数是闭包的一个特例 ({}) // 闭包实例 // `->` 分隔了闭包的参数和返回值 @@ -276,17 +286,10 @@ numbers = numbers.map({ number in 3 * number }) print(numbers) // [3, 6, 18] // 简洁的闭包 -numbers = sorted(numbers) { $0 > $1 } -// 函数的最后一个参数可以放在括号之外,上面的语句是这个语句的简写形式 -// numbers = sorted(numbers, { $0 > $1 }) +numbers = numbers.sort { $0 > $1 } print(numbers) // [18, 6, 3] -// 超级简洁的闭包,因为 `<` 是个操作符函数 -numbers = sorted(numbers, < ) - -print(numbers) // [3, 6, 18] - // // MARK: 结构体 @@ -295,8 +298,8 @@ print(numbers) // [3, 6, 18] // 结构体和类非常类似,可以有属性和方法 struct NamesTable { - let names = [String]() - + let names: [String] + // 自定义下标运算符 subscript(index: Int) -> String { return names[index] @@ -306,7 +309,7 @@ struct NamesTable { // 结构体有一个自动生成的隐含的命名构造函数 let namesTable = NamesTable(names: ["Me", "Them"]) let name = namesTable[1] -println("Name is \(name)") // Name is Them +print("Name is \(name)") // Name is Them // // MARK: 类 @@ -329,7 +332,7 @@ public class Shape { internal class Rect: Shape { // 值属性 (Stored properties) var sideLength: Int = 1 - + // 计算属性 (Computed properties) private var perimeter: Int { get { @@ -340,11 +343,11 @@ internal class Rect: Shape { sideLength = newValue / 4 } } - + // 延时加载的属性,只有这个属性第一次被引用时才进行初始化,而不是定义时就初始化 // subShape 值为 nil ,直到 subShape 第一次被引用时才初始化为一个 Rect 实例 lazy var subShape = Rect(sideLength: 4) - + // 监控属性值的变化。 // 当我们需要在属性值改变时做一些事情,可以使用 `willSet` 和 `didSet` 来设置监控函数 // `willSet`: 值改变之前被调用 @@ -352,14 +355,14 @@ internal class Rect: Shape { var identifier: String = "defaultID" { // `willSet` 的参数是即将设置的新值,参数名可以指定,如果没有指定,就是 `newValue` willSet(someIdentifier) { - println(someIdentifier) + print(someIdentifier) } // `didSet` 的参数是已经被覆盖掉的旧的值,参数名也可以指定,如果没有指定,就是 `oldValue` didSet { - println(oldValue) + print(oldValue) } } - + // 命名构造函数 (designated inits),它必须初始化所有的成员变量, // 然后调用父类的命名构造函数继续初始化父类的所有变量。 init(sideLength: Int) { @@ -367,13 +370,13 @@ internal class Rect: Shape { // 必须显式地在构造函数最后调用父类的构造函数 super.init super.init() } - + func shrink() { if sideLength > 0 { --sideLength } } - + // 函数重载使用 override 关键字 override func getArea() -> Int { return sideLength * sideLength @@ -394,16 +397,16 @@ class Square: Rect { } var mySquare = Square() -println(mySquare.getArea()) // 25 +print(mySquare.getArea()) // 25 mySquare.shrink() -println(mySquare.sideLength) // 4 +print(mySquare.sideLength) // 4 // 类型转换 let aShape = mySquare as Shape // 使用三个等号来比较是不是同一个实例 if mySquare === aShape { - println("Yep, it's mySquare") + print("Yep, it's mySquare") } class Circle: Shape { @@ -411,12 +414,12 @@ class Circle: Shape { override func getArea() -> Int { return 3 * radius * radius } - + // optional 构造函数,可能会返回 nil init?(radius: Int) { self.radius = radius super.init() - + if radius <= 0 { return nil } @@ -425,13 +428,13 @@ class Circle: Shape { // 根据 Swift 类型推断,myCircle 是 Optional<Circle> 类型的变量 var myCircle = Circle(radius: 1) -println(myCircle?.getArea()) // Optional(3) -println(myCircle!.getArea()) // 3 +print(myCircle?.getArea()) // Optional(3) +print(myCircle!.getArea()) // 3 var myEmptyCircle = Circle(radius: -1) -println(myEmptyCircle?.getArea()) // "nil" +print(myEmptyCircle?.getArea()) // "nil" if let circle = myEmptyCircle { // 此语句不会输出,因为 myEmptyCircle 变量值为 nil - println("circle is not nil") + print("circle is not nil") } @@ -461,7 +464,7 @@ enum BookName: String { case John = "John" case Luke = "Luke" } -println("Name: \(BookName.John.rawValue)") +print("Name: \(BookName.John.rawValue)") // 与特定数据类型关联的枚举 enum Furniture { @@ -469,7 +472,7 @@ enum Furniture { case Desk(height: Int) // 和 String, Int 关联的枚举记录 case Chair(brand: String, height: Int) - + func description() -> String { switch self { case .Desk(let height): @@ -481,9 +484,9 @@ enum Furniture { } var desk: Furniture = .Desk(height: 80) -println(desk.description()) // "Desk with 80 cm" +print(desk.description()) // "Desk with 80 cm" var chair = Furniture.Chair(brand: "Foo", height: 40) -println(chair.description()) // "Chair of Foo with 40 cm" +print(chair.description()) // "Chair of Foo with 40 cm" // @@ -506,21 +509,21 @@ protocol ShapeGenerator { // 一个类实现一个带 optional 方法的协议时,可以实现或不实现这个方法 // optional 方法可以使用 optional 规则来调用 @objc protocol TransformShape { - optional func reshaped() + optional func reshape() optional func canReshape() -> Bool } class MyShape: Rect { var delegate: TransformShape? - + func grow() { sideLength += 2 // 在 optional 属性,方法或下标运算符后面加一个问号,可以优雅地忽略 nil 值,返回 nil。 // 这样就不会引起运行时错误 (runtime error) - if let allow = self.delegate?.canReshape?() { + if let reshape = self.delegate?.canReshape?() where reshape { // 注意语句中的问号 - self.delegate?.reshaped?() + self.delegate?.reshape?() } } } @@ -532,33 +535,33 @@ class MyShape: Rect { // 扩展: 给一个已经存在的数据类型添加功能 -// 给 Square 类添加 `Printable` 协议的实现,现在其支持 `Printable` 协议 -extension Square: Printable { +// 给 Square 类添加 `CustomStringConvertible` 协议的实现,现在其支持 `CustomStringConvertible` 协议 +extension Square: CustomStringConvertible { var description: String { return "Area: \(self.getArea()) - ID: \(self.identifier)" } } -println("Square: \(mySquare)") // Area: 16 - ID: defaultID +print("Square: \(mySquare)") // Area: 16 - ID: defaultID // 也可以给系统内置类型添加功能支持 extension Int { var customProperty: String { return "This is \(self)" } - + func multiplyBy(num: Int) -> Int { return num * self } } -println(7.customProperty) // "This is 7" -println(14.multiplyBy(3)) // 42 +print(7.customProperty) // "This is 7" +print(14.multiplyBy(3)) // 42 // 泛型: 和 Java 及 C# 的泛型类似,使用 `where` 关键字来限制类型。 // 如果只有一个类型限制,可以省略 `where` 关键字 -func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { - for (index, value) in enumerate(array) { +func findIndex<T: Equatable>(array: [T], _ valueToFind: T) -> Int? { + for (index, value) in array.enumerate() { if value == valueToFind { return index } @@ -566,7 +569,7 @@ func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { return nil } let foundAtIndex = findIndex([1, 2, 3, 4], 3) -println(foundAtIndex == 2) // true +print(foundAtIndex == 2) // true // 自定义运算符: // 自定义运算符可以以下面的字符打头: @@ -581,11 +584,24 @@ prefix func !!! (inout shape: Square) -> Square { } // 当前值 -println(mySquare.sideLength) // 4 +print(mySquare.sideLength) // 4 // 使用自定义的 !!! 运算符来把矩形边长放大三倍 !!!mySquare -println(mySquare.sideLength) // 12 +print(mySquare.sideLength) // 12 -``` +// 运算符也可以是泛型 +infix operator <-> {} +func <-><T: Equatable> (inout a: T, inout b: T) { + let c = a + a = b + b = c +} +var foo: Float = 10 +var bar: Float = 20 + +foo <-> bar +print("foo is \(foo), bar is \(bar)") // "foo is 20.0, bar is 10.0" + +``` diff --git a/zh-cn/tmux-cn.html.markdown b/zh-cn/tmux-cn.html.markdown new file mode 100644 index 00000000..cf865dce --- /dev/null +++ b/zh-cn/tmux-cn.html.markdown @@ -0,0 +1,253 @@ +--- +category: tool +tool: tmux +filename: LearnTmux-cn.txt +contributors: + - ["mdln", "https://github.com/mdln"] +translators: + - ["Arnie97", "https://github.com/Arnie97"] +lang: zh-cn +--- + + +[tmux](http://tmux.github.io)是一款终端复用工具。 +在它的帮助下,你可以在同一个控制台上建立、访问并控制多个终端。 +你可以断开与一个 tmux 终端的连接,此时程序将在后台运行, +当你需要时,可以随时重新连接到这个终端。 + +``` + + tmux [command] # 运行一条命令 + # 如果单独使用 'tmux' 而不指定某个命令,将会建立一个新的会话 + + new # 创建一个新的会话 + -s "Session" # 创建一个会话,并命名为“Session” + -n "Window" # 创建一个窗口,并命名为“Window” + -c "/dir" # 在指定的工作目录中启动会话 + + attach # 连接到上一次的会话(如果可用) + -t "#" # 连接到指定的会话 + -d # 断开其他客户端的会话 + + ls # 列出打开的会话 + -a # 列出所有打开的会话 + + lsw # 列出窗口 + -a # 列出所有窗口 + -s # 列出会话中的所有窗口 + + lsp # 列出窗格 + -a # 列出所有窗格 + -s # 列出会话中的所有窗格 + -t "#" # 列出指定窗口中的所有窗格 + + kill-window # 关闭当前窗口 + -t "#" # 关闭指定的窗口 + -a # 关闭所有窗口 + -a -t "#" # 关闭除指定窗口以外的所有窗口 + + kill-session # 关闭当前会话 + -t "#" # 关闭指定的会话 + -a # 关闭所有会话 + -a -t "#" # 关闭除指定会话以外的所有会话 + +``` + + +### 快捷键 + +通过“前缀”快捷键,可以控制一个已经连入的 tmux 会话。 + +``` +---------------------------------------------------------------------- + (C-b) = Ctrl + b # 在使用下列快捷键之前,需要按这个“前缀”快捷键 + + (M-1) = Meta + 1 或 Alt + 1 +---------------------------------------------------------------------- + + ? # 列出所有快捷键 + : # 进入 tmux 的命令提示符 + r # 强制重绘当前客户端 + c # 创建一个新窗口 + + ! # 将当前窗格从窗口中移出,成为为一个新的窗口 + % # 将当前窗格分为左右两半 + " # 将当前窗格分为上下两半 + + n # 切换到下一个窗口 + p # 切换到上一个窗口 + { # 将当前窗格与上一个窗格交换 + } # 将当前窗格与下一个窗格交换 + + s # 在交互式界面中,选择并连接至另一个会话 + w # 在交互式界面中,选择并激活一个窗口 + 0 至 9 # 选择 0 到 9 号窗口 + + d # 断开当前客户端 + D # 选择并断开一个客户端 + + & # 关闭当前窗口 + x # 关闭当前窗格 + + Up, Down # 将焦点移动至相邻的窗格 + Left, Right + + M-1 到 M-5 # 排列窗格: + # 1) 水平等分 + # 2) 垂直等分 + # 3) 将一个窗格作为主要窗格,其他窗格水平等分 + # 4) 将一个窗格作为主要窗格,其他窗格垂直等分 + # 5) 平铺 + + C-Up, C-Down # 改变当前窗格的大小,每按一次增减一个单位 + C-Left, C-Right + + M-Up, M-Down # 改变当前窗格的大小,每按一次增减五个单位 + M-Left, M-Right + +``` + + +### 配置 ~/.tmux.conf + +tmux.conf 可以在 tmux 启动时自动设置选项,类似于 .vimrc 或 init.el 的用法。 + +``` +# tmux.conf 示例 +# 2014.10 + + +### 通用设置 +########################################################################### + +# 启用 UTF-8 编码 +setw -g utf8 on +set-option -g status-utf8 on + +# 命令回滚/历史数量限制 +set -g history-limit 2048 + +# 从 1 开始编号,而不是从 0 开始 +set -g base-index 1 + +# 启用鼠标 +set-option -g mouse-select-pane on + +# 重新加载配置文件 +unbind r +bind r source-file ~/.tmux.conf + + +### 快捷键设置 +########################################################################### + +# 取消默认的前缀键 C-b +unbind C-b + +# 设置新的前缀键 ` +set-option -g prefix ` + +# 多次按下前缀键时,切换到上一个窗口 +bind C-a last-window +bind ` last-window + +# 按下F11/F12,可以选择不同的前缀键 +bind F11 set-option -g prefix C-a +bind F12 set-option -g prefix ` + +# Vim 风格的快捷键绑定 +setw -g mode-keys vi +set-option -g status-keys vi + +# 使用 Vim 风格的按键在窗格间移动 +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R + +# 循环切换不同的窗口 +bind e previous-window +bind f next-window +bind E swap-window -t -1 +bind F swap-window -t +1 + +# 较易于使用的窗格分割快捷键 +bind = split-window -h +bind - split-window -v +unbind '"' +unbind % + +# 在嵌套使用 tmux 的情况下,激活最内层的会话,以便向其发送命令 +bind a send-prefix + + +### 外观主题 +########################################################################### + +# 状态栏颜色 +set-option -g status-justify left +set-option -g status-bg black +set-option -g status-fg white +set-option -g status-left-length 40 +set-option -g status-right-length 80 + +# 窗格边框颜色 +set-option -g pane-active-border-fg green +set-option -g pane-active-border-bg black +set-option -g pane-border-fg white +set-option -g pane-border-bg black + +# 消息框颜色 +set-option -g message-fg black +set-option -g message-bg green + +# 窗口状态栏颜色 +setw -g window-status-bg black +setw -g window-status-current-fg green +setw -g window-status-bell-attr default +setw -g window-status-bell-fg red +setw -g window-status-content-attr default +setw -g window-status-content-fg yellow +setw -g window-status-activity-attr default +setw -g window-status-activity-fg yellow + + +### 用户界面 +########################################################################### + +# 通知方式 +setw -g monitor-activity on +set -g visual-activity on +set-option -g bell-action any +set-option -g visual-bell off + +# 自动设置窗口标题 +set-option -g set-titles on +set-option -g set-titles-string '#H:#S.#I.#P #W #T' # 窗口编号,程序名称,是否活动 + +# 调整状态栏 +set -g status-left "#[fg=red] #H#[fg=green]:#[fg=white]#S#[fg=green] |#[default]" + +# 在状态栏中显示性能计数器 +# 需要用到 https://github.com/thewtex/tmux-mem-cpu-load +set -g status-interval 4 +set -g status-right "#[fg=green] | #[fg=white]#(tmux-mem-cpu-load)#[fg=green] | #[fg=cyan]%H:%M #[default]" + +``` + + +### 参考资料 + +[Tmux 主页](http://tmux.github.io) + +[Tmux 手册](http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/tmux.1?query=tmux) + +[FreeBSDChina Wiki](https://wiki.freebsdchina.org/software/t/tmux) + +[Archlinux Wiki](https://wiki.archlinux.org/index.php/Tmux_(简体中文)) + +[Tmux 快速教程](http://blog.jeswang.org/blog/2013/06/24/tmux-kuai-su-jiao-cheng) + +[如何在 tmux 状态栏中显示 CPU / 内存占用的百分比](https://stackoverflow.com/questions/11558907/is-there-a-better-way-to-display-cpu-usage-in-tmux) + +[管理复杂 tmux 会话的工具 - tmuxinator](https://github.com/tmuxinator/tmuxinator) diff --git a/zh-cn/typescript-cn.html.markdown b/zh-cn/typescript-cn.html.markdown new file mode 100644 index 00000000..2651b1cb --- /dev/null +++ b/zh-cn/typescript-cn.html.markdown @@ -0,0 +1,173 @@ +--- +language: TypeScript +category: language +contributors: + - ["Philippe Vlérick", "https://github.com/pvlerick"] +translators: + - ["Shawn Zhang", "https://github.com/shawnzhang009"] +filename: learntypescript-cn.ts +lang: zh-cn +--- + +TypeScript是一门为开发大型JavaScript应用而设计的语言。TypeScript在JavaScript的基础上增加了类、模块、接口、泛型和静态类型(可选)等常见的概念。它是JavaScript的一个超集:所有JavaScript代码都是有效的TypeScript代码,所以任何JavaScript项目都可以无缝引入TypeScript. TypeScript编译器会把TypeScript代码编译成JavaScript代码。 + +本文只关注TypeScript额外增加的区别于[JavaScript](../javascript-cn/)的语法,. + +如需测试TypeScript编译器,你可以在[Playground](http://www.typescriptlang.org/Playground)码代码,它会自动编译成JavaScript代码然后直接显示出来。 + +```js +// TypeScript有三种基本类型 +var isDone: boolean = false; +var lines: number = 42; +var name: string = "Anders"; + +// 如果不知道是什么类型,可以使用"any"(任意)类型 +var notSure: any = 4; +notSure = "maybe a string instead"; +notSure = false; // 亦可,定义为布尔型 + +// 对于集合的声明, 有类型化数组和泛型数组 +var list: number[] = [1, 2, 3]; +// 另外一种,使用泛型数组 +var list: Array<number> = [1, 2, 3]; + +// 枚举: +enum Color {Red, Green, Blue}; +var c: Color = Color.Green; + +// 最后,"void"用于函数没有任何返回的特殊情况下 +function bigHorribleAlert(): void { + alert("I'm a little annoying box!"); +} + +// 函数是"第一等公民"(first class citizens), 支持使用箭头表达式和类型推断 + +// 以下是相等的,TypeScript编译器会把它们编译成相同的JavaScript代码 +var f1 = function(i: number): number { return i * i; } +// 返回推断类型的值 +var f2 = function(i: number) { return i * i; } +var f3 = (i: number): number => { return i * i; } +// 返回推断类型的值 +var f4 = (i: number) => { return i * i; } +// 返回推断类型的值, 单行程式可以不需要return关键字和大括号 +var f5 = (i: number) => i * i; + +// 接口是结构化的,任何具有这些属性的对象都与该接口兼容 +interface Person { + name: string; + // 可选属性,使用"?"标识 + age?: number; + // 函数 + move(): void; +} + +// 实现"Person"接口的对象,当它有了"name"和"move"方法之后可被视为一个"Person" +var p: Person = { name: "Bobby", move: () => {} }; +// 带了可选参数的对象 +var validPerson: Person = { name: "Bobby", age: 42, move: () => {} }; +// 因为"age"不是"number"类型所以这不是一个"Person" +var invalidPerson: Person = { name: "Bobby", age: true }; + +// 接口同样可以描述一个函数的类型 +interface SearchFunc { + (source: string, subString: string): boolean; +} +// 参数名并不重要,参数类型才是重要的 +var mySearch: SearchFunc; +mySearch = function(src: string, sub: string) { + return src.search(sub) != -1; +} + +// 类 - 成员默认为公共的(public) +class Point { + // 属性 + x: number; + + // 构造器 - 这里面的public/private关键字会为属性生成样板代码和初始化值 + // 这个例子中,y会被同x一样定义,不需要额外代码 + // 同样支持默认值 + + constructor(x: number, public y: number = 0) { + this.x = x; + } + + // 函数 + dist() { return Math.sqrt(this.x * this.x + this.y * this.y); } + + // 静态成员 + static origin = new Point(0, 0); +} + +var p1 = new Point(10 ,20); +var p2 = new Point(25); //y为0 + +// 继承 +class Point3D extends Point { + constructor(x: number, y: number, public z: number = 0) { + super(x, y); // 必须显式调用父类的构造器 + } + + // 重写 + dist() { + var d = super.dist(); + return Math.sqrt(d * d + this.z * this.z); + } +} + +// 模块, "."可以作为子模块的分隔符 +module Geometry { + export class Square { + constructor(public sideLength: number = 0) { + } + area() { + return Math.pow(this.sideLength, 2); + } + } +} + +var s1 = new Geometry.Square(5); + +// 引入模块并定义本地别名 +import G = Geometry; + +var s2 = new G.Square(10); + +// 泛型 +// 类 +class Tuple<T1, T2> { + constructor(public item1: T1, public item2: T2) { + } +} + +// 接口 +interface Pair<T> { + item1: T; + item2: T; +} + +// 以及函数 +var pairToTuple = function<T>(p: Pair<T>) { + return new Tuple(p.item1, p.item2); +}; + +var tuple = pairToTuple({ item1:"hello", item2:"world"}); + +// 引用定义文件 +// <reference path="jquery.d.ts" /> + +// 模板字符串(使用反引号的字符串) +// 嵌入变量的模板字符串 +var name = 'Tyrone'; +var greeting = `Hi ${name}, how are you?` +// 有多行内容的模板字符串 +var multiline = `This is an example +of a multiline string`; + +``` + +## 参考资料 + * [TypeScript官网](http://www.typescriptlang.org/) + * [TypeScript语言规范说明书(pdf)](http://go.microsoft.com/fwlink/?LinkId=267238) + * [Anders Hejlsberg - TypeScript介绍](http://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript) + * [GitHub源码](https://github.com/Microsoft/TypeScript) + * [Definitely Typed - 类型定义仓库](http://definitelytyped.org/) diff --git a/zh-cn/zfs-cn.html.markdown b/zh-cn/zfs-cn.html.markdown new file mode 100644 index 00000000..fdf5277e --- /dev/null +++ b/zh-cn/zfs-cn.html.markdown @@ -0,0 +1,397 @@ +--- +category: tool +tool: zfs +contributors: + - ["sarlalian", "http://github.com/sarlalian"] +translators: + - ["Alan Cheng", "https://github.com/kedaio"] +filename: LearnZfs-cn.txt +lang: zh-cn +--- + +[ZFS](http://open-zfs.org/wiki/Main_Page) +是重新思考与储存相关技术的结果,它把传统的文件系统和卷管理器集成到一个工具当中. +ZFS不但有把它和传统存储系统分开来的特有术语,也有很多聚焦于可用性的功能。 + + +## ZFS概念 + +### 虚拟设备(Virtual Devices,VDEV) + +对于操作系统来说,VDEV和传统的RAID阵列卡所呈现的raid设备类似。VDEV有几种不同的类型,每种类型 +都有自己的优势,包括冗余和速度。一般来说,VDEV的可靠性和安全性比阵列卡要好。因此使用ZFS时不 +建议使用阵列卡。让ZFS直接管理磁盘。 + +VDEV的类型 +* stripe (条带。单个磁盘,没有冗余) +* mirror (镜像。支持n-way镜像) +* raidz + * raidz1 (一个奇偶校验磁盘, 类似于RAID 5) + * raidz2 (两个奇偶校验磁盘, 类似于RAID 6) + * raidz3 (三个奇偶校验磁盘, 没有类似RAID等级) +* disk (磁盘) +* file (文件。不推荐在生产环境中使用,因为中间又多了一层不必要的文件系统) + +数据会以条带方式存储于存储池中的所有VDEV上。因此一个存储池中的VDEV越多,IOPS就越高。 + +### storage pool (存储池) + +ZFS 使用存储池来作为底层存储提供者(VDEV)的抽象。这样可以把用户可见的文件系统和底层的物理磁盘 +布局分离开来。 + +### ZFS 数据集(Dataset) + +ZFS 数据集类似于传统的文件系统(译者注:或者说是目录),但是提供了更多的功能。ZFS的很多优势也是 +在这一层体现出来的。数据集支持 [Copy on Write](https://en.wikipedia.org/wiki/Copy-on-write) +快照, 配额, 压缩和重复消除(de-duplication). + + +### 限制 + +一个目录最多可包含 2^48个文件, 每个文件最大可以是16 exabytes. 一个存储池最大可包含256 zettabytes 、 +(2^78) 的空间, 可以条带化地分布于2^64 设备上. 单一主机最多可以创建2^64个存储池。这些限制可以说是相 +当大。 + + +## 命令 + +### 存储池 + +Actions: (存储池操作) +* List (列举) +* Status (查看状态) +* Destroy (删除) +* Get/Set properties (获取/设置属性) + +List zpools (列举存储池(也叫zpool)) + +```bash +# 创建一个raidz类型的存储池(名称为bucket) +$ zpool create bucket raidz1 gpt/zfs0 gpt/zfs1 gpt/zfs2 + +# 列出所有存储池 +$ zpool list +NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT +zroot 141G 106G 35.2G - 43% 75% 1.00x ONLINE - + +# 列出某一存储池的详细信息 +$ zpool list -v zroot +NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT +zroot 141G 106G 35.2G - 43% 75% 1.00x ONLINE - + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 141G 106G 35.2G - 43% 75% +``` + +Status of zpools (存储池状态) + +```bash +# 获取全部zpool状态信息 +$ zpool status + pool: zroot + state: ONLINE + scan: scrub repaired 0 in 2h51m with 0 errors on Thu Oct 1 07:08:31 2015 +config: + + NAME STATE READ WRITE CKSUM + zroot ONLINE 0 0 0 + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 ONLINE 0 0 0 + +errors: No known data errors + +# 用scrub来更正存储池错误信息 +$ zpool scrub zroot +$ zpool status -v zroot + pool: zroot + state: ONLINE + scan: scrub in progress since Thu Oct 15 16:59:14 2015 + 39.1M scanned out of 106G at 1.45M/s, 20h47m to go + 0 repaired, 0.04% done +config: + + NAME STATE READ WRITE CKSUM + zroot ONLINE 0 0 0 + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 ONLINE 0 0 0 + +errors: No known data errors +``` + +Properties of zpools (存储池属性) + +```bash + +# 获取某一存储池的全部属性。属性可能是系统提供,也可能是用户设置 +$ zpool get all zroot +NAME PROPERTY VALUE SOURCE +zroot size 141G - +zroot capacity 75% - +zroot altroot - default +zroot health ONLINE - +... + +# 设置存储池属性,下例这是设置comment(备注)属性 +$ zpool set comment="Storage of mah stuff" zroot +$ zpool get comment +NAME PROPERTY VALUE SOURCE +tank comment - default +zroot comment Storage of mah stuff local +``` + +Remove zpool (删除存储池) + +```bash +$ zpool destroy test +``` + + +### Datasets (数据集) + +Actions: (数据集相关操作) +* Create (创建) +* List (列举) +* Rename (重命名) +* Delete (删除) +* Get/Set properties (获取/设置属性) + +Create datasets + +```bash +# 创建数据集 +$ zfs create tank/root/data +$ mount | grep data +tank/root/data on /data (zfs, local, nfsv4acls) + +# 创建子数据集 +$ zfs create tank/root/data/stuff +$ mount | grep data +tank/root/data on /data (zfs, local, nfsv4acls) +tank/root/data/stuff on /data/stuff (zfs, local, nfsv4acls) + + +# 创建卷 +$ zfs create -V zroot/win_vm +$ zfs list zroot/win_vm +NAME USED AVAIL REFER MOUNTPOINT +tank/win_vm 4.13G 17.9G 64K - +``` + +List datasets (列举数据集) + +```bash +# 列出所有数据集 +$ zfs list +NAME USED AVAIL REFER MOUNTPOINT +zroot 106G 30.8G 144K none +zroot/ROOT 18.5G 30.8G 144K none +zroot/ROOT/10.1 8K 30.8G 9.63G / +zroot/ROOT/default 18.5G 30.8G 11.2G / +zroot/backup 5.23G 30.8G 144K none +zroot/home 288K 30.8G 144K none +... + +# 列举某一数据集的信息 +$ zfs list zroot/home +NAME USED AVAIL REFER MOUNTPOINT +zroot/home 288K 30.8G 144K none + +# 列出快照 +$ zfs list -t snapshot +zroot@daily-2015-10-15 0 - 144K - +zroot/ROOT@daily-2015-10-15 0 - 144K - +zroot/ROOT/default@daily-2015-10-15 0 - 24.2G - +zroot/tmp@daily-2015-10-15 124K - 708M - +zroot/usr@daily-2015-10-15 0 - 144K - +zroot/home@daily-2015-10-15 0 - 11.9G - +zroot/var@daily-2015-10-15 704K - 1.42G - +zroot/var/log@daily-2015-10-15 192K - 828K - +zroot/var/tmp@daily-2015-10-15 0 - 152K - +``` + +Rename datasets (重命名数据集) + +```bash +$ zfs rename tank/root/home tank/root/old_home +$ zfs rename tank/root/new_home tank/root/home +``` + +Delete dataset (删除数据集) + +```bash +# 数据集如果有快照则无法删除 +zfs destroy tank/root/home +``` + +Get / set properties of a dataset (获取/设置数据集属性) + +```bash +# 获取数据集全部属性 +$ zfs get all zroot/usr/home │157 # Create Volume +NAME PROPERTY VALUE SOURCE │158 $ zfs create -V zroot/win_vm +zroot/home type filesystem - │159 $ zfs list zroot/win_vm +zroot/home creation Mon Oct 20 14:44 2014 - │160 NAME USED AVAIL REFER MOUNTPOINT +zroot/home used 11.9G - │161 tank/win_vm 4.13G 17.9G 64K - +zroot/home available 94.1G - │162 ``` +zroot/home referenced 11.9G - │163 +zroot/home mounted yes - +... + +# 获取数据集属性 +$ zfs get compression zroot/usr/home +NAME PROPERTY VALUE SOURCE +zroot/home compression off default + +# 设置数据集属性(下例为设置压缩属性compression) +$ zfs set compression=gzip-9 mypool/lamb + +# 列举所有数据集的名称、配额和预留属性 +$ zfs list -o name,quota,reservation +NAME QUOTA RESERV +zroot none none +zroot/ROOT none none +zroot/ROOT/default none none +zroot/tmp none none +zroot/usr none none +zroot/home none none +zroot/var none none +... +``` + + +### Snapshots (快照) + +快照是ZFS 的一个非常重要的功能 + +* 快照占用的空间等于它和原始数据的差异量 +* 创建时间以秒计 +* 恢复时间和写入速度相同 +* 易于自动化 + +Actions: (快照相关操作) +* Create (创建) +* Delete (删除) +* Rename (重命名) +* Access snapshots (访问) +* Send / Receive (发送/接收) +* Clone (克隆。译者注:关于clone和快照的区别可参看[这里](http://docs.oracle.com/cd/E19253-01/819-5461/gbcxz/index.html)) + + +Create snapshots (创建快照) + +```bash +# 为单一数据集创建快照 +zfs snapshot tank/home/sarlalian@now + +# 为数据集及其子集创建快照 +$ zfs snapshot -r tank/home@now +$ zfs list -t snapshot +NAME USED AVAIL REFER MOUNTPOINT +tank/home@now 0 - 26K - +tank/home/sarlalian@now 0 - 259M - +tank/home/alice@now 0 - 156M - +tank/home/bob@now 0 - 156M - +... + +Destroy snapshots (删除快照) + +```bash +# 如何删除快照 +$ zfs destroy tank/home/sarlalian@now + +# 删除某一数据集及其子集的快照 +$ zfs destroy -r tank/home/sarlalian@now + +``` + +Renaming Snapshots (重命名) + +```bash +# 重命名快照 +$ zfs rename tank/home/sarlalian@now tank/home/sarlalian@today +$ zfs rename tank/home/sarlalian@now today + +# zfs rename -r tank/home@now @yesterday +``` + +Accessing snapshots (访问快照) + +```bash +# cd进入一个快照目录 +$ cd /home/.zfs/snapshot/ +``` + +Sending and Receiving + +```bash +# 备份快照到一个文件 +$ zfs send tank/home/sarlalian@now | gzip > backup_file.gz + +# 发送快照到另一个数据集 +$ zfs send tank/home/sarlalian@now | zfs recv backups/home/sarlalian + +# 发送快照到一个远程主机 +$ zfs send tank/home/sarlalian@now | ssh root@backup_server 'zfs recv tank/home/sarlalian' + +# 发送完整数据集及其快照到一个新主机 +$ zfs send -v -R tank/home@now | ssh root@backup_server 'zfs recv tank/home' +``` + +Cloneing Snapshots (克隆快照) + +```bash +# 克隆一个快照 +$ zfs clone tank/home/sarlalian@now tank/home/sarlalian_new + +# 提升克隆,让它不再依赖原始快照 +$ zfs promote tank/home/sarlalian_new +``` + +### 汇总 + +下面这个脚本使用了FreeBSD, jails和ZFS,来自动在一个mysql群集的热备主机上为一个mysq staging数据库 +创建一份纯净的拷贝。 + +```bash +#!/bin/sh + +echo "==== Stopping the staging database server ====" +jail -r staging + +echo "==== Cleaning up existing staging server and snapshot ====" +zfs destroy -r zroot/jails/staging +zfs destroy zroot/jails/slave@staging + +echo "==== Quiescing the slave database ====" +echo "FLUSH TABLES WITH READ LOCK;" | /usr/local/bin/mysql -u root -pmyrootpassword -h slave + +echo "==== Snapshotting the slave db filesystem as zroot/jails/slave@staging ====" +zfs snapshot zroot/jails/slave@staging + +echo "==== Starting the slave database server ====" +jail -c slave + +echo "==== Cloning the slave snapshot to the staging server ====" +zfs clone zroot/jails/slave@staging zroot/jails/staging + +echo "==== Installing the staging mysql config ====" +mv /jails/staging/usr/local/etc/my.cnf /jails/staging/usr/local/etc/my.cnf.slave +cp /jails/staging/usr/local/etc/my.cnf.staging /jails/staging/usr/local/etc/my.cnf + +echo "==== Setting up the staging rc.conf file ====" +mv /jails/staging/etc/rc.conf.local /jails/staging/etc/rc.conf.slave +mv /jails/staging/etc/rc.conf.staging /jails/staging/etc/rc.conf.local + +echo "==== Starting the staging db server ====" +jail -c staging + +echo "==== Makes the staging database not pull from the master ====" +echo "STOP SLAVE;" | /usr/local/bin/mysql -u root -pmyrootpassword -h staging +echo "RESET SLAVE;" | /usr/local/bin/mysql -u root -pmyrootpassword -h staging +``` + + +### 延伸阅读 + +* [BSDNow's Crash Course on ZFS](http://www.bsdnow.tv/tutorials/zfs) +* [FreeBSD Handbook on ZFS](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/zfs.html) +* [BSDNow's Crash Course on ZFS](http://www.bsdnow.tv/tutorials/zfs) +* [Oracle's Tuning Guide](http://www.oracle.com/technetwork/articles/servers-storage-admin/sto-recommended-zfs-settings-1951715.html) +* [OpenZFS Tuning Guide](http://open-zfs.org/wiki/Performance_tuning) +* [FreeBSD ZFS Tuning Guide](https://wiki.freebsd.org/ZFSTuningGuide) |