diff options
Diffstat (limited to 'zh-cn')
| -rw-r--r-- | zh-cn/crystal-cn.html.markdown | 567 | ||||
| -rw-r--r-- | zh-cn/dart-cn.html.markdown | 4 | ||||
| -rw-r--r-- | zh-cn/kotlin-cn.html.markdown | 33 | ||||
| -rw-r--r-- | zh-cn/make-cn.html.markdown | 262 | ||||
| -rw-r--r-- | zh-cn/typescript-cn.html.markdown | 2 | 
5 files changed, 848 insertions, 20 deletions
| diff --git a/zh-cn/crystal-cn.html.markdown b/zh-cn/crystal-cn.html.markdown new file mode 100644 index 00000000..14805114 --- /dev/null +++ b/zh-cn/crystal-cn.html.markdown @@ -0,0 +1,567 @@ +--- +language: crystal +filename: learncrystal-cn.cr +contributors: +    - ["Vitalii Elenhaupt", "http://veelenga.com"] +    - ["Arnaud Fernandés", "https://github.com/TechMagister/"] +translators: +    - ["Xuty", "https://github.com/xtyxtyx"] +lang: zh-cn +--- + +```crystal + +# 这是一行注释 + +# 一切都是对象(object) +nil.class  #=> Nil +100.class  #=> Int32 +true.class #=> Bool + +# nil, false 以及空指针是假值(falsey values) +!nil   #=> true  : Bool +!false #=> true  : Bool +!0     #=> false : Bool + +# 整数类型 + +1.class #=> Int32 + +# 四种有符号整数 +1_i8.class  #=> Int8 +1_i16.class #=> Int16 +1_i32.class #=> Int32 +1_i64.class #=> Int64 + +# 四种无符号整数 +1_u8.class  #=> UInt8 +1_u16.class #=> UInt16 +1_u32.class #=> UInt32 +1_u64.class #=> UInt64 + +2147483648.class          #=> Int64 +9223372036854775808.class #=> UInt64 + +# 二进制数 +0b1101 #=> 13 : Int32 + +# 八进制数 +0o123 #=> 83 : Int32 + +# 十六进制数 +0xFE012D #=> 16646445 : Int32 +0xfe012d #=> 16646445 : Int32 + +# 浮点数类型 + +1.0.class #=> Float64 + +# Crystal中有两种浮点数 +1.0_f32.class #=> Float32 +1_f32.class   #=> Float32 + +1e10.class    #=> Float64 +1.5e10.class  #=> Float64 +1.5e-7.class  #=> Float64 + +# 字符类型 + +'a'.class #=> Char + +# 八进制字符 +'\101' #=> 'A' : Char + +# Unicode字符 +'\u0041' #=> 'A' : Char + +# 字符串 + +"s".class #=> String + +# 字符串不可变(immutable) +s = "hello, "  #=> "hello, "        : String +s.object_id    #=> 134667712        : UInt64 +s += "Crystal" #=> "hello, Crystal" : String +s.object_id    #=> 142528472        : UInt64 + +# 支持字符串插值(interpolation) +"sum = #{1 + 2}" #=> "sum = 3" : String + +# 多行字符串 +"这是一个 +   多行字符串" + +# 书写带有引号的字符串 +%(hello "world") #=> "hello \"world\"" + +# 符号类型 +# 符号是不可变的常量,本质上是Int32类型 +# 符号通常被用来代替字符串,来高效地传递特定的值 + +:symbol.class #=> Symbol + +sentence = :question?     # :"question?" : Symbol + +sentence == :question?    #=> true  : Bool +sentence == :exclamation! #=> false : Bool +sentence == "question?"   #=> false : Bool + +# 数组类型(Array) + +[1, 2, 3].class         #=> Array(Int32) +[1, "hello", 'x'].class #=> Array(Int32 | String | Char) + +# 必须为空数组指定类型 +[]               # Syntax error: for empty arrays use '[] of ElementType' +[] of Int32      #=> [] : Array(Int32) +Array(Int32).new #=> [] : Array(Int32) + +# 数组可以通过下标访问 +array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] : Array(Int32) +array[0]                #=> 1               : Int32 +array[10]               # raises IndexError +array[-6]               # raises IndexError +array[10]?              #=> nil             : (Int32 | Nil) +array[-6]?              #=> nil             : (Int32 | Nil) + +# 使用负位置编号,从后往前访问数组 +array[-1] #=> 5 + +# With a start index and size +# 使用起始位置编号+大小 +array[2, 3] #=> [3, 4, 5] + +# 使用范围(range)访问数组 +array[1..3] #=> [2, 3, 4] + +# 向尾部添加元素 +array << 6  #=> [1, 2, 3, 4, 5, 6] + +# 删除尾部元素 +array.pop #=> 6 +array     #=> [1, 2, 3, 4, 5] + +# 删除首部元素 +array.shift #=> 1 +array       #=> [2, 3, 4, 5] + +# 检查元素是否存在与数组之中 +array.includes? 3 #=> true + +# 一种特殊语法,用来创建字符串数组或符号数组 +%w(one two three) #=> ["one", "two", "three"] : Array(String) +%i(one two three) #=> [:one, :two, :three]    : Array(Symbol) + +# 对于定义了`new`和`#<<`方法的类,可以用以下语法创建新对象 +set = Set{1, 2, 3} #=> [1, 2, 3] +set.class          #=> Set(Int32) + +# 以下代码与上方等同 +set = Set(typeof(1, 2, 3)).new +set << 1 +set << 2 +set << 3 + +# 哈希表类型(Hash) + +{1 => 2, 3 => 4}.class   #=> Hash(Int32, Int32) +{1 => 2, 'a' => 3}.class #=> Hash(Int32 | Char, Int32) + +# 必须为空哈希表指定类型 +{}                     # Syntax error +{} of Int32 => Int32   # {} +Hash(Int32, Int32).new # {} + +# 可以使用键(key)快速查询哈希表 +hash = {"color" => "green", "number" => 5} +hash["color"]        #=> "green" +hash["no_such_key"]  #=> Missing hash key: "no_such_key" (KeyError) +hash["no_such_key"]? #=> nil + +# 检查某一键哈希表中是否存在 +hash.has_key? "color" #=> true + +# 对于定义了`#[]=`方法的类,可以使用以下语法创建对象 +class MyType +  def []=(key, value) +    puts "do stuff" +  end +end + +MyType{"foo" => "bar"} + +# 以上与下列代码等同 +tmp = MyType.new +tmp["foo"] = "bar" +tmp + +# 范围类型(Range) + +1..10                  #=> Range(Int32, Int32) +Range.new(1, 10).class #=> Range(Int32, Int32) + +# 包含或不包含端点 +(3..5).to_a  #=> [3, 4, 5] +(3...5).to_a #=> [3, 4] + +# 检查某一值是否在范围内 +(1..8).includes? 2 #=> true + +# 元组类型(Tuple) + +# 元组类型尺寸固定,不可变,储存在栈中 +# 元组可以有不同类型的对象组成 +{1, "hello", 'x'}.class #=> Tuple(Int32, String, Char) + +# 使用下标访问元组 +tuple = {:key1, :key2} +tuple[1] #=> :key2 +tuple[2] #=> syntax error : Index out of bound + +# 将元组中的元素赋值给变量 +a, b, c = {:a, 'b', "c"} +a #=> :a +b #=> 'b' +c #=> "c" + +# 命名元组类型(NamedTuple) + +tuple = {name: "Crystal", year: 2011} # NamedTuple(name: String, year: Int32) +tuple[:name] # => "Crystal" (String) +tuple[:year] # => 2011      (Int32) + +# 命名元组的键可以是字符串常量 +{"this is a key": 1} # => NamedTuple("this is a key": Int32) + +# 过程类型(Proc) +# 过程代表一个函数指针,以及可选的上下文(闭包) +# 过程通常使用字面值创建 +proc = ->(x : Int32) { x.to_s } +proc.class # Proc(Int32, String) + +# 或者使用`new`方法创建 +Proc(Int32, String).new { |x| x.to_s } + +# 使用`call`方法调用过程 +proc.call 10 #=> "10" + +# 控制语句(Control statements) + +if true +  "if 语句" +elsif false +  "else-if, 可选" +else +  "else, 同样可选" +end + +puts "可以将if后置" if true + +# 将if作为表达式 +a = if 2 > 1 +      3 +    else +      4 +    end + +a #=> 3 + +# 条件表达式 +a = 1 > 2 ? 3 : 4 #=> 4 + +# `case`语句 +cmd = "move" + +action = case cmd +  when "create" +    "Creating..." +  when "copy" +    "Copying..." +  when "move" +    "Moving..." +  when "delete" +    "Deleting..." +end + +action #=> "Moving..." + +# 循环 +index = 0 +while index <= 3 +  puts "Index: #{index}" +  index += 1 +end +# Index: 0 +# Index: 1 +# Index: 2 +# Index: 3 + +index = 0 +until index > 3 +  puts "Index: #{index}" +  index += 1 +end +# Index: 0 +# Index: 1 +# Index: 2 +# Index: 3 + +# 更好的做法是使用`each` +(0..3).each do |index| +  puts "Index: #{index}" +end +# Index: 0 +# Index: 1 +# Index: 2 +# Index: 3 + +# 变量的类型取决于控制语句中表达式的类型 +if a < 3 +  a = "hello" +else +  a = true +end +typeof a #=> (Bool | String) + +if a && b +  # 此处`a`与`b`均为Nil +end + +if a.is_a? String +  a.class #=> String +end + +# 函数(Functions) + +def double(x) +  x * 2 +end + +# 函数(以及所有代码块)均将最末尾表达式的值作为返回值 +double(2) #=> 4 + +# 在没有歧义的情况下,括号可以省略 +double 3 #=> 6 + +double double 3 #=> 12 + +def sum(x, y) +  x + y +end + +# 使用逗号分隔参数 +sum 3, 4 #=> 7 + +sum sum(3, 4), 5 #=> 12 + +# yield +# 所有函数都有一个默认生成、可选的代码块(block)参数 +# 在函数中可以使用yield调用此代码块 + +def surround +  puts '{' +  yield +  puts '}' +end + +surround { puts "hello world" } + +# { +# hello world +# } + + +# 可将代码块作为参数传给函数 +# "&" 表示对代码块参数的引用 +def guests(&block) +  block.call "some_argument" +end + +# 使用星号"*"将参数转换成元组 +def guests(*array) +  array.each { |guest| puts guest } +end + +# 如果函数返回数组,可以将其解构 +def foods +    ["pancake", "sandwich", "quesadilla"] +end +breakfast, lunch, dinner = foods +breakfast #=> "pancake" +dinner    #=> "quesadilla" + +# 按照约定,所有返回布尔值的方法都以问号结尾 +5.even? # false +5.odd?  # true + +# 以感叹号结尾的方法,都有一些破坏性(destructive)行为,比如改变调用接收者(receiver) +# 对于某些方法,带有感叹号的版本将改变调用接收者,而不带有感叹号的版本返回新值 +company_name = "Dunder Mifflin" +company_name.gsub "Dunder", "Donald"  #=> "Donald Mifflin" +company_name  #=> "Dunder Mifflin" +company_name.gsub! "Dunder", "Donald" +company_name  #=> "Donald Mifflin" + + +# 使用`class`关键字来定义类(class) +class Human + +  # 类变量,由类的所有实例所共享 +  @@species = "H. sapiens" + +  # `name`的类型为`String` +  @name : String + +  # 构造器方法(initializer) +  # 其中@name、@age为简写,相当于 +  # +  # def initialize(name, age = 0) +  #   @name = name +  #   @age = age +  # end +  # +  # `age`为可选参数,如果未指定,则使用默认值0 +  def initialize(@name, @age = 0) +  end + +  # @name的setter方法 +  def name=(name) +    @name = name +  end + +  # @name的getter方法 +  def name +    @name +  end + +  # 上述getter与setter的定义可以用property宏简化 +  property :name + +  # 也可用getter与setter宏独立创建getter与setter +  getter :name +  setter :name + +  # 此处的`self.`使`say`成为类方法 +  def self.say(msg) +    puts msg +  end + +  def species +    @@species +  end +end + + +# 将类实例化 +jim = Human.new("Jim Halpert") + +dwight = Human.new("Dwight K. Schrute") + +# 调用一些实例方法 +jim.species #=> "H. sapiens" +jim.name #=> "Jim Halpert" +jim.name = "Jim Halpert II" #=> "Jim Halpert II" +jim.name #=> "Jim Halpert II" +dwight.species #=> "H. sapiens" +dwight.name #=> "Dwight K. Schrute" + +# 调用类方法 +Human.say("Hi") #=> 输出 Hi ,返回 nil + +# 带有`@`前缀的变量为实例变量 +class TestClass +  @var = "I'm an instance var" +end + +# 带有`@@`前缀的变量为类变量 +class TestClass +  @@var = "I'm a class var" +end +# 首字母大写的变量为常量 +Var = "这是一个常量" +Var = "无法再次被赋值" # 常量`Var`已经被初始化 + +# 在crystal中类也是对象(object),因此类也有实例变量(instance variable) +# 类变量的定义由类以及类的派生类所共有,但类变量的值是独立的 + +# 基类 +class Human +  @@foo = 0 + +  def self.foo +    @@foo +  end + +  def self.foo=(value) +    @@foo = value +  end +end + +# 派生类 +class Worker < Human +end + +Human.foo   #=> 0 +Worker.foo  #=> 0 + +Human.foo = 2 #=> 2 +Worker.foo    #=> 0 + +Worker.foo = 3 #=> 3 +Human.foo   #=> 2 +Worker.foo  #=> 3 + +module ModuleExample +  def foo +    "foo" +  end +end + +# include <Module> 将模块(module)中的方法添加为实例方法 +# extend <Module>  将模块中的方法添加为类方法 + +class Person +  include ModuleExample +end + +class Book +  extend ModuleExample +end + +Person.foo     # => undefined method 'foo' for Person:Class +Person.new.foo # => 'foo' +Book.foo       # => 'foo' +Book.new.foo   # => undefined method 'foo' for Book + + +# 异常处理 + +# 定义新的异常类(exception) +class MyException < Exception +end + +# 再定义一个异常类 +class MyAnotherException < Exception; end + +ex = begin +   raise MyException.new +rescue ex1 : IndexError +  "ex1" +rescue ex2 : MyException | MyAnotherException +  "ex2" +rescue ex3 : Exception +  "ex3" +rescue ex4 # 捕捉任何类型的异常 +  "ex4" +end + +ex #=> "ex2" + +``` + +## 参考资料 + +- [官方网站](https://crystal-lang.org/) +- [官方文档](https://crystal-lang.org/docs/overview/) +- [在线运行代码](https://play.crystal-lang.org/#/cr) +- [Github仓库](https://github.com/crystal-lang/crystal) diff --git a/zh-cn/dart-cn.html.markdown b/zh-cn/dart-cn.html.markdown index 6a6562bc..b0287f0c 100644 --- a/zh-cn/dart-cn.html.markdown +++ b/zh-cn/dart-cn.html.markdown @@ -492,8 +492,8 @@ main() {  Dart 有一个综合性网站。它涵盖了 API 参考、入门向导、文章以及更多,  还包括一个有用的在线试用 Dart 页面。 -http://www.dartlang.org/ -http://try.dartlang.org/ +* [https://www.dartlang.org](https://www.dartlang.org) +* [https://try.dartlang.org](https://try.dartlang.org) diff --git a/zh-cn/kotlin-cn.html.markdown b/zh-cn/kotlin-cn.html.markdown index 5d655029..f6dcd847 100644 --- a/zh-cn/kotlin-cn.html.markdown +++ b/zh-cn/kotlin-cn.html.markdown @@ -22,7 +22,7 @@ package com.learnxinyminutes.kotlin  /*  Kotlin程序的入口点是一个"main"函数 -该函数传递一个包含任何命令行参数的数组。 +该函数传递一个包含所有命令行参数的数组。  */  fun main(args: Array<String>) {      /* @@ -67,10 +67,10 @@ fun helloWorld(val name : String) {      模板表达式从一个美元符号($)开始。      */      val fooTemplateString = "$fooString has ${fooString.length} characters" -    println(fooTemplateString) +    println(fooTemplateString) // => 输出 My String Is Here! has 18 characters      /* -    当某个变量的值可以为 null 的时候,我们必须被明确指定它是可为空的。 +    当某个变量的值可以为 null 的时候,我们必须明确指定它是可为空的。      在变量声明处的类型后面加上?来标识它是可为空的。      我们可以用?.操作符来访问可为空的变量。      我们可以用?:操作符来指定一个在变量为空时使用的替代值。 @@ -96,24 +96,24 @@ fun helloWorld(val name : String) {      println(hello()) // => Hello, world!      /* -    用"vararg"关键字来修饰一个函数的参数来允许可变参数传递给该函数 +    函数的可变参数可使用 "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 +    varargExample() // => 传入 0 个参数 +    varargExample(1) // => 传入 1 个参数 +    varargExample(1, 2, 3) // => 传入 3 个参数      /* -    当函数只包含一个单独的表达式时,大括号可以被省略。 -    函数体可以被指定在一个=符号后面。 +    当函数只包含一个单独的表达式时,大括号可以省略。 +    函数体可以写在一个=符号后面。      */      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 @@ -122,15 +122,14 @@ fun helloWorld(val name : String) {      fun not(f: (Int) -> Boolean) : (Int) -> Boolean {          return {n -> !f.invoke(n)}      } -    // 命名函数可以用::运算符被指定为参数。 +    // 普通函数可以用::运算符传入引用作为函数参数。      val notOdd = not(::odd)      val notEven = not(::even) -    // 匿名函数可以被指定为参数。 +    // lambda 表达式可以直接作为参数传递。      val notZero = not {n -> n == 0}      /* -    如果一个匿名函数只有一个参数 -    那么它的声明可以被省略(连同->)。 -    这个参数的名字是"it"。 +    如果一个 lambda 表达式只有一个参数 +    那么它的声明可以省略(连同->),内部以 "it" 引用。      */      val notPositive = not {it > 0}      for (i in 0..4) { @@ -152,7 +151,7 @@ fun helloWorld(val name : String) {      注意,Kotlin没有"new"关键字。      */      val fooExampleClass = ExampleClass(7) -    // 可以使用一个点号来调用成员函数。 +    // 可以使用一个点号来调用成员方法。      println(fooExampleClass.memberFunction(4)) // => 11      /*      如果使用"infix"关键字来标记一个函数 @@ -162,7 +161,7 @@ fun helloWorld(val name : String) {      /*      数据类是创建只包含数据的类的一个简洁的方法。 -    "hashCode"、"equals"和"toString"方法将被自动生成。 +    "hashCode"、"equals"和"toString"方法将自动生成。      */      data class DataClassExample (val x: Int, val y: Int, val z: Int)      val fooData = DataClassExample(1, 2, 4) diff --git a/zh-cn/make-cn.html.markdown b/zh-cn/make-cn.html.markdown new file mode 100644 index 00000000..4cdf1e63 --- /dev/null +++ b/zh-cn/make-cn.html.markdown @@ -0,0 +1,262 @@ +--- +language: make +contributors: +- ["Robert Steed", "https://github.com/robochat"] +- ["Jichao Ouyang", "https://github.com/jcouyang"] +translators: +- ["Jichao Ouyang", "https://github.com/jcouyang"] +filename: Makefile-cn +lang: zh-cn +--- + +Makefile 用于定义如何创建目标文件, 比如如何从源码到可执行文件. 创建这一工具的目标是 +减少不必要的编译或者任务.是传说中的 Stuart Feldman 在 1976 年花了一个周末写出来的,  +而今仍然使用广泛, 特别是在 Unix 和 Linux 系统上. + +虽然每个语言可能都有相应的或多或少提供 make 的功能, 比如 ruby 的 rake, node 的 gulp, broccoli +, scala 的 sbt 等等. 但是 make 的简洁与高效, 和只做一件事并做到极致的风格, 使其至今仍是无可替代的, +甚至与其他构建工具一起使用也并无冲突. + +尽管有许多的分支和变体, 这篇文章针对是标准的 GNU make. + +```make +# 这行表示注释 + +# 文件名一定要交 Makefile, 大小写区分, 使用 `make <target>` 生成 target +# 如果想要取别的名字, 可以用 `make -f "filename" <target>`. + +# 重要的事情 - 只认识 TAB, 空格是不认的, 但是在 GNU Make 3.82 之后, 可以通过 +# 设置参数 .RECIPEPREFIX 进行修改 + +#----------------------------------------------------------------------- +# 初级 +#----------------------------------------------------------------------- + +# 创建一个 target 的规则非常简单 +# targets : prerequisites +# 	recipe +# 	 … +# prerequisites(依赖) 是可选的, recipe(做法) 也可以多个或者不给. + +# 下面这个任务没有给 prerequisites, 只会在目标文件 file0.txt 文件不存在是跑 +file0.txt: +	echo "foo" > file0.txt +	# 试试 `make file0.txt` +	# 或者直接 `make`, 因为第一个任务是默认任务. +	# 注意: 即使是这些注释, 如果前面有 TAB, 也会发送给 shell, 注意看 `make file0.txt` 输出 + +# 如果提供 prerequisites, 则只有 prerequisites 比 target 新时会执行 +# 比如下面这个任务只有当 file1.txt 比 file0.txt 新时才会执行. +file1.txt: file0.txt +	cat file0.txt > file1.txt +	# 这里跟shell里的命令式一毛一样的. +	@cat file0.txt >> file1.txt +	# @ 不会把命令往 stdout 打印. +	-@echo 'hello' +	# - 意思是发生错误了也没关系. +	# 试试 `make file1.txt` 吧. + +# targets 和 prerequisites 都可以是多个, 以空格分割 +file2.txt file3.txt: file0.txt file1.txt +	touch file2.txt +	touch file3.txt + +# 如果声明重复的 target, make 会给一个 warning, 后面会覆盖前面的 +# 比如重复定义 file2.txt 会得到这样的 warning +# Makefile:46: warning: overriding commands for target `file2.txt' +# Makefile:40: warning: ignoring old commands for target `file2.txt' +file2.txt: file0.txt +	touch file2.txt + +# 但是如果不定义任何 recipe, 就不会冲突, 只是多了依赖关系 +file2.txt: file0.txt file3.txt + +#----------------------------------------------------------------------- +# Phony(假的) Targets +#----------------------------------------------------------------------- + +# phony targets 意思是 tagets 并不是文件, 可以想象成一个任务的名字而已. +# 因为不是文件, 无法比对是否有更新, 所以每次make都会执行. +all: maker process + +# 依赖于 phony target 的 target 也会每次 make 都执行, 即使 target 是文件 +ex0.txt ex1.txt: maker + +# target 的声明顺序并不重要, 比如上面的 all 的依赖 maker 现在才声明 +maker: +	touch ex0.txt ex1.txt + +# 如果定义的 phony target 与文件名重名, 可以用 .PHONY 显示的指明哪些 targets 是 phony +.PHONY: all maker process +# This is a special target. There are several others. + +# 常用的 phony target 有: all clean install ... + +#----------------------------------------------------------------------- +# 变量与通配符 +#----------------------------------------------------------------------- + +process: file*.txt | dir/a.foo.b	# 可以用通配符匹配多个文件作为prerequisites +	@echo $^	# $^ 是 prerequisites +	@echo $@	# $@ 代表 target, 如果 target 为多个, $@ 代表当前执行的那个 +	@echo $<	# $< prerequisite 中的第一个 +	@echo $?	# $? 需要更新的 prerequisite 文件列表 +	@echo $+	# $+ 所有依赖, 包括重复的 +	@echo $|	# $| 竖线后面的 order-only prerequisites + +a.%.b: +	@echo $*  # $* match 的target % 那部分, 包括路径, 比如 `make dir/a.foo.b` 会打出 `dir/foo` + +# 即便分开定义依赖, $^ 依然能拿到 +process: ex1.txt file0.txt +# 非常智能的, ex1.txt 会被找到, file0.txt 会被去重. + +#----------------------------------------------------------------------- +# 模式匹配 +#----------------------------------------------------------------------- + +# 可以让 make 知道如何转换某些文件到别格式 +# 比如 从 svg 到 png +%.png: %.svg +	inkscape --export-png $^ + +# 一旦有需要 foo.png 这个任务就会运行 + +# 路径会被忽略, 所以上面的 target 能匹配所有 png +# 但是如果加了路径, make 会找到最接近的匹配, 如果 +# make small/foo.png (在这之前要先有 small/foo.svg 这个文件) +# 则会匹配下面这个规则 +small/%.png: %.svg +	inkscape --export-png --export-dpi 30 $^ + +%.png: %.svg +	@echo 重复定义会覆盖前面的, 现在 inkscape 没用了 + +# make 已经有一些内置的规则, 比如从 *.c 到 *.o + +#----------------------------------------------------------------------- +# 变量 +#----------------------------------------------------------------------- +# 其实是宏 macro + +# 变量都是字符串类型, 下面这俩是一样一样的 + +name = Ted +name2="Sarah" + +echo: +	@echo $(name) +	@echo ${name2} +	@echo $name    # 这个会被蠢蠢的解析成 $(n)ame. +	@echo \"$(name3)\" # 为声明的变量或扩展成空字符串. +	@echo $(name4) +	@echo $(name5) +# 你可以通过4种方式设置变量. +# 按以下顺序由高到低: +# 1: 命令行参数. 比如试试 `make echo name3=JICHAO` +# 2: Makefile 里面的 +# 3: shell 中的环境变量 +# 4: make 预设的一些变量 + +name4 ?= Jean +# 问号意思是如果 name4 被设置过了, 就不设置了. + +override name5 = David +# 用 override 可以防止命令行参数设置的覆盖 + +name4 +=grey +# 用加号可以连接 (中间用空格分割). + +# 在依赖的地方设置变量 +echo: name2 = Sara2 + +# 还有一些内置的变量 +echo_inbuilt: +	echo $(CC) +	echo ${CXX)} +	echo $(FC) +	echo ${CFLAGS)} +	echo $(CPPFLAGS) +	echo ${CXXFLAGS} +	echo $(LDFLAGS) +	echo ${LDLIBS} + +#----------------------------------------------------------------------- +# 变量 2 +#----------------------------------------------------------------------- + +# 加个冒号可以声明 Simply expanded variables 即时扩展变量, 即只在声明时扩展一次 +# 之前的等号声明时 recursively expanded 递归扩展 + +var := hello +var2 :=  $(var) hello + +# 这些变量会在其引用的顺序求值 +# 比如 var3 声明时找不到 var4, var3 会扩展成 `and good luck` +var3 := $(var4) and good luck +# 但是一般的变量会在调用时递归扩展, 先扩展 var5, 再扩展 var4, 所以是正常的 +var5 = $(var4) and good luck +var4 := good night + +echoSEV: +	@echo $(var) +	@echo $(var2) +	@echo $(var3) +	@echo $(var4) +	@echo $(var5) + +#----------------------------------------------------------------------- +# 函数 +#----------------------------------------------------------------------- + +# make 自带了一些函数. +# wildcard 会将后面的通配符变成一串文件路径 +all_markdown: +	@echo $(wildcard *.markdown) +# patsubst 可以做替换, 比如下面会把所有 markdown +# 后缀的文件重命名为 md 后缀 +substitue: * +	@echo $(patsubst %.markdown,%.md,$* $^) + +# 函数调用格式是 $(func arg0,arg1,arg2...) + +# 试试 +ls:	* +	@echo $(filter %.txt, $^) +	@echo $(notdir $^) +	@echo $(join $(dir $^),$(notdir $^)) + +#----------------------------------------------------------------------- +# Directives +#----------------------------------------------------------------------- + +# 可以用 include 引入别的 Makefile 文件 +# include foo.mk + +sport = tennis +# 一些逻辑语句 if else 什么的, 顶个写 +report: +ifeq ($(sport),tennis) +	@echo 'game, set, match' +else +	@echo "They think it's all over; it is now" +endif + +# 还有 ifneq, ifdef, ifndef + +foo = true + +# 不只是 recipe, 还可以写在外面哟 +ifdef $(foo) +bar = 'bar' +endif + +hellobar: +	@echo bar +``` + +### 资源 + ++ GNU Make 官方文档 [HTML](https://www.gnu.org/software/make/manual/) [PDF](https://www.gnu.org/software/make/manual/make.pdf) ++ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/) ++ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html) diff --git a/zh-cn/typescript-cn.html.markdown b/zh-cn/typescript-cn.html.markdown index 2651b1cb..032f89e4 100644 --- a/zh-cn/typescript-cn.html.markdown +++ b/zh-cn/typescript-cn.html.markdown @@ -153,7 +153,7 @@ var pairToTuple = function<T>(p: Pair<T>) {  var tuple = pairToTuple({ item1:"hello", item2:"world"});  // 引用定义文件 -// <reference path="jquery.d.ts" /> +/// <reference path="jquery.d.ts" />  // 模板字符串(使用反引号的字符串)  // 嵌入变量的模板字符串 | 
