3.0 总体介绍

  • Scala中的if/then/else结构和Java中很像,但是它还可以用来返回一个值。比如Java中用的三目运算,在Scala中只需要使用正常的if语句即可。

    val x = if (a) y else z
    
  • try/catch/finilly结构和Java中很像,但是Scala中的catch部分使用的是模式匹配。
  • Scala中可以使用2个for循环读取文件的每行,然后在每行上操作每个字符:

    for (line <- source.getLines) {for {char <- lineif char.isLetter} // char algorithm here ...
    }
    
  • 在Scala中,还可以更加简单点:

    for {line <- source.getLineschar <- lineif char.isLetter
    } // char algorithm here ...
    
  • Scala很容易对一个集合进行操作并产生一个新的集合:

    scala> val nieces = List("emily", "hannah", "mercedes", "porsche")
    nieces: List[String] = List(emily, hannah, mercedes, porsche)scala> for (n <- nieces) yield n.capitalize
    res0: List[String] = List(Emily, Hannah, Mercedes, Porsche)
    
  • 类似的,基本用法中Scala的匹配表达式和Java的Switch语句很像,但是匹配模式可以匹配任何对象,从匹配的对象中提取信息,添加case分支,返回结果而且更多。匹配表达式是Scala语言的一大特色。

3.1 使用for和foreach循环

  • 问题:想要遍历集合中的元素,或者操作集合中的每个元素,或者根据已有集合创建一个新集合。

3.1.1 解决方案

  • 有很多循环Scala集合的方法,包括for循环,while循环,foreach、map、flatMap等集合方法。该方案主要针对for循环和foreach方法。

    val a = Array("apple", "banana", "orange")//for循环
    scala> for (e <- a) println(e)
    apple
    banana
    orange
    
  • 多行数据处理,使用for循环,并且类代码块里执行

    scala> for (e <- a) {| // imagine this requires multiple lines| val s = e.toUpperCase| println(s)| }
    APPLE
    BANANA
    ORANGE
    

3.1.2 for循环返回值

  • 使用for/yield组合根据输入集合创建一个新的集合:

    scala> val newArray = for (e <- a) yield e.toUpperCase
    newArray: Array[java.lang.String] = Array(APPLE, BANANA, ORANGE)
    
  • 注意输入类型是Array,输出也是Array,而不是其他比如Vector
  • 在yield关键词后使用代码块处理多行代码:

    scala> val newArray = for (e <- a) yield {| // imagine this requires multiple lines| val s = e.toUpperCase| s| }
    newArray: Array[java.lang.String] = Array(APPLE, BANANA, ORANGE)
    

3.1.3 for循环计数器

  • 使用计数器获取数组元素

    for (i <- 0 until a.length) {println(s"$i is ${a(i)}")
    }//输出
    0 is apple
    1 is banana
    2 is orange
    
  • 使用zipWithIndex方法创建一个循环计数器

    scala> for ((e, count) <- a.zipWithIndex) {| println(s"$count is $e")| }
    0 is apple
    1 is banana
    2 is orange
    
  • 更多zipWithIndex看10.11章

3.1.4 生成

  • 使用Range执行3次for循环

    scala> for (i <- 1 to 3) println(i)
    1
    2
    3
    
  • 使用1 to 3创建一个Range

    scala> 1 to 3
    res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3)
    
  • 章节3.3演示如何使用guards,这里简单预览下:

    scala> for (i <- 1 to 10 if i < 4) println(i)
    1
    2
    3
    

3.1.5 Map的循环

  • 当循环Map里的键和值时,下面循环方法简明可读:

    val names = Map("fname" -> "Robert","lname" -> "Goren")
    for ((k,v) <- names) println(s"key: $k, value: $v")
    
  • 更多查看11.17章

3.1.6 讨论

  • for/yield组合是创建并返回一个新集合。但是没有yield的for循环只是操作集合中的每个元素,并没有创建一个新集合。for/yield组合基本使用就像map方法一样。更多看3.4章
  • for循环并不一定是最好的解决问题的方法。foreach,map,flatMap,collect,reduce等等方法经常被用来解决问题,而不要求使用for循环。
  • 可以通过foreach循环每个元素

    scala> a.foreach(println)
    apple
    banana
    orange
    
  • 需要在集合每个元素上进行数据处理,使用匿名函数语法:

    scala> a.foreach(e => println(e.toUpperCase))
    APPLE
    BANANA
    ORANGE
    
  • 需要多行数据处理,使用代码块

    scala> a.foreach { e =>| val s = e.toUpperCase| println(s)| }
    APPLE
    BANANA
    ORANGE
    

3.1.7 for循环如何被翻译

  • Scala Language Specification 提供了在不同环境for循环被翻译的精确细节。可以总结为以下四点:

    • 简单for循环被翻译成集合上的foreach方法调用
    • 使用guard(3.3章)的for循环被翻译成集合上使用withFilter方法的序列,后面跟着foreach调用
    • for/yield组合表达式被翻译成集合上的map方法调用
    • for/yield/guard组合被翻译成集合上使用withFilter方法,后面跟着map调用
  • 使用下面的scalac命令行提供Scala编译器翻译for循环为其他代码的初始化输出:

    $ scalac -Xprint:parse Main.scala
    
  • 在一个命名为Main.scala的文件中写以下代码

    class Main {for (i <- 1 to 10) println(i)
    }
    
  • 使用scalac命令行后输出如下

    $ scalac -Xprint:parse Main.scala[[syntax trees at end of parser]] // Main.scala
    package <empty> {class Main extends scala.AnyRef {def <init>() = {super.<init>();()};1.to(10).foreach(((i) => println(i)))}
    }
    
  • 如果使用 -Xprint:all 选项代替 -Xprint:parse 编译文件,会发现代码进一步被被翻译成下面的代码,包括太多编译时的细节:

    $ scalac -Xprint:all Main.scalascala.this.Predef.intWrapper(1).to(10).foreach[Unit]
    (((i: Int) => scala.this.Predef.println(i)))
    
  • 上面使用的是Range,但是在其他集合编译器表现一样。下例使用list代替Range:

    // original List code
    val nums = List(1,2,3)
    for (i <- nums) println(i)// translation performed by the compiler
    val nums = List(1,2,3)
    nums.foreach(((i) => println(i)))
    
  • 下面演示各种for循环如何被翻译:

    • 第一个代码

      // #1 - input (my code)
      for (i <- 1 to 10) println(i)// #1 - compiler output
      1.to(10).foreach(((i) => println(i)))
      
    • 添加guard(if语句)

      // #2 - input code
      for {i <- 1 to 10if i % 2 == 0
      } println(i)// #2 - translated output
      1.to(10).withFilter(((i) => i.$percent(2).$eq$eq(0))).foreach(((i) =>println(i)))
      
    • 两个guard被翻译成两个withFilter调用

      // #3 - input code
      for {i <- 1 to 10if i != 1if i % 2 == 0
      } println(i)// #3 - translated output
      1.to(10).withFilter(((i) => i.$bang$eq(1))).withFilter(((i)=> i.$percent(2).$eq$eq(0))).foreach(((i) => println(i)))
      
    • for/yield组合

      // #4 - input code
      for { i <- 1 to 10 } yield i// #4 - output
      1.to(10).map(((i) => i))
      
    • for/yield/guard组合

      // #5 - input code (for loop, guard, and yield)
      for {i <- 1 to 10if i % 2 == 0
      } yield i// #5 - translated code
      1.to(10).withFilter(((i) => i.$percent(2).$eq$eq(0))).map(((i) => i))
      

3.2 使用多个计数器的for循环

  • 问题:当你循环多维数组时,需要创建一个带有多个计数器的循环。

3.2.1 解决方案

  • 如下方法创建:

    scala> for (i <- 1 to 2; j <- 1 to 2) println(s"i = $i, j = $j")
    i = 1, j = 1
    i = 1, j = 2
    i = 2, j = 1
    i = 2, j = 2
    
  • 对于多行for循环首选的格式是花括号:

    for {i <- 1 to 2j <- 1 to 2
    } println(s"i = $i, j = $j")
    
  • 三个计数器:

    for {i <- 1 to 3j <- 1 to 5k <- 1 to 10
    } println(s"i = $i, j = $j, k = $k")
    
  • 当循环多维数组时非常有用,假设创建一个二维数组:

    val array = Array.ofDim[Int](2,2)
    array(0)(0) = 0
    array(0)(1) = 1
    array(1)(0) = 2
    array(1)(1) = 3
    
  • 通过以下方式打印数组的每个元素:

    scala> for {| i <- 0 to 1| j <- 0 to 1| } println(s"($i)($j) = ${array(i)(j)}")
    (0)(0) = 0
    (0)(1) = 1
    (1)(0) = 2
    (1)(1) = 3
    

3.2.2 讨论

  • 在for循环里使用符号<-创建的Range指的是生成器,可以在一个循环里使用多个生成器。
  • 较长for循环里推荐格式是使用大括号:
    for {
    i <- 1 to 2
    j <- 2 to 3
    } println(s”i = i,j=i, j = j”)
  • 这种格式比其他格式可扩展性高,这里指的是在表达式里添加更多生成器和guards后依旧可读性高
  • 查看更多

    Scala Style Guide page on formatting control


3.3 使用加入if语句的for循环

  • 问题:想要在for循环添加一个或者更多条件语句用来过滤掉集合中的某些元素。

3.3.1 解决方案

  • 在生成器后添加if语句

    // print all even numbers
    scala> for (i <- 1 to 10 if i % 2 == 0) println(i)
    2
    4
    6
    8
    10
    
  • 或者使用大括号格式:

    for {i <- 1 to 10if i % 2 == 0
    } println(i)
    
  • 使用多个if语句

    for {i <- 1 to 10if i > 3if i < 6if i % 2 == 0
    } println(i)
    

3.3.2 讨论

  • 在for循环里使用if语句简明可读性高,当然也可以使用传统方式

    for (file <- files) {if (hasSoundFileExtension(file) && !soundFileIsLong(file)) {soundFiles += file}
    }
    
  • 一旦习惯Scala的for循环语句,下面的方式更加可读,因为它从业务逻辑中把循环和过滤分开:

    for {file <- filesif passesFilter1(file)if passesFilter2(file)
    } doSomething(file)
    

3.4 创建一个for/yield组合

  • 问题:在已有集合上每个元素进行运算处理创建一个新的集合

3.4.1 解决方案

  • 使用yield

    scala> val names = Array("chris", "ed", "maurice")
    names: Array[String] = Array(chris, ed, maurice)scala> val capNames = for (e <- names) yield e.capitalize
    capNames: Array[String] = Array(Chris, Ed, Maurice)
    
  • 多行运算处理,在yield关键词之后使用代码块执行工作

    scala> val lengths = for (e <- names) yield {| // imagine that this required multiple lines of code| e.length| }
    lengths: Array[Int] = Array(5, 2, 7)
    
  • 除了特殊情况,for循环集合返回类型和开始类型是一样的。举例如果循环一个ArrayBuffer,那么返回也是ArrayBuffer

    //原集合
    var fruits = scala.collection.mutable.ArrayBuffer[String]()
    fruits += "apple"
    fruits += "banana"
    fruits += "orange"//新集合
    scala> val out = for (e <- fruits) yield e.toUpperCase
    out: scala.collection.mutable.ArrayBuffer[java.lang.String] =ArrayBuffer(APPLE, BANANA, ORANGE)
    
  • 输入时List集合,那么for/yield循环之后返回也是List集合

    scala> val fruits = "apple" :: "banana" :: "orange" :: Nil
    fruits: List[java.lang.String] = List(apple, banana, orange)scala> val out = for (e <- fruits) yield e.toUpperCase
    out: List[java.lang.String] = List(APPLE, BANANA, ORANGE)
    

3.4.2 讨论

  • for/yield工作原理

    • 开始运行时,for/yield循环立刻创建一个和输入集合一样的新的空的集合。比如输入类型是Vector,那么输出就是Vector,可以认为新集合是一个桶。
    • 每次循环,从输入集合的当前元素创建一个新的输出元素,当输出元素创建,就被放置在桶中。
    • 循环结束时,返回这个桶的所有内容。
  • 没有guard的for/yield组合和调用map方法一样:

    scala> val out = for (e <- fruits) yield e.toUpperCase
    out: List[String] = List(APPLE, BANANA, ORANGE)scala> val out = fruits.map(_.toUpperCase)
    out: List[String] = List(APPLE, BANANA, ORANGE)
    

3.5 实现break和continue

  • 问题:有一个需要使用break和continue结构的情况,但是Scala没有break和continue关键词

3.5.1 解决方案

  • Scala没有break和continue关键词,但在scala.util.control.Breaks提供了相同的功能

    package com.alvinalexander.breakandcontinueimport util.control.Breaks._object BreakAndContinueDemo extends App {println("\n=== BREAK EXAMPLE ===")breakable {for (i <- 1 to 10) {println(i)if (i > 4) break // break out of the for loop}}println("\n=== CONTINUE EXAMPLE ===")val searchMe = "peter piper picked a peck of pickled peppers"var numPs = 0for (i <- 0 until searchMe.length) {breakable {if (searchMe.charAt(i) != 'p') {break // break out of the 'breakable', continue the outside loop} else {numPs += 1}}}println("Found " + numPs + " p's in the string.")
    }//输出
    === BREAK EXAMPLE ===
    1
    2
    3
    4
    5=== CONTINUE EXAMPLE ===
    Found 9 p's in the string.
    

3.5.2 break例子

  • 当i大于4时,运行break“关键词”,此时会抛出一个异常,并且for循环退出。breakable“关键词”捕获这个异常然后运行breakable语句块之后的代码

    breakable {for (i <- 1 to 10) {println(i)if (i > 4) break // break out of the for loop}
    }
    
  • 注意break和breakable并不是真的关键词,他们是scala.util.control.Breaks里的方法。在Scala2.10,break方法被调用时会抛出一个BreakControl异常实例

    private val breakException = new BreakControl
    def break(): Nothing = { throw breakException }
    
  • breakable方法定义成捕获一个BreakControl异常

    def breakable(op: => Unit) {try {op} catch {case ex: BreakControl =>if (ex ne breakException) throw ex}
    }
    
  • 更多看3.18章,如何与Breaks库类似的方式实现自己的控制结构

3.5.3 continue例子

  • 代码循环字符串中的每个字符,如果当前字符不是字母p,那么跳出if/then语句,然后继续执行for循环。
  • 执行到break方法后,抛出一个异常,然后被breakable捕获。这个异常跳出if/then语句,然后捕获以允许for循环继续执行后面的元素。

    val searchMe = "peter piper picked a peck of pickled peppers"
    var numPs = 0for (i <- 0 until searchMe.length) {breakable {if (searchMe.charAt(i) != 'p') {break // break out of the 'breakable', continue the outside loop} else {numPs += 1}}
    }println("Found " + numPs + " p's in the string.")
    

3.5.4 一般语法

  • 实现break和continue功能的一般的语法如下,部分以伪代码方式写,然后与java进行比较。

    //break Scala
    breakable {for (x <- xs) {if (cond)break}
    }//break Java
    for (X x : xs) {if (cond) break;
    }//continue Scala
    for (x <- xs) {breakable {if (cond)break}
    }//continue Java
    for (X x : xs) {if (cond) continue;
    }
    

3.5.5 关于continue例子

  • 在Scala中有更好的方法解决continue例子的问题,比如直接的方法是以简单匿名函数使用count方法,此时count依旧是9:

    val count = searchMe.count(_ == 'p')
    

3.5.6 嵌套循环和标记break

  • 在任何情况下,可以创建标记break:

    object LabeledBreakDemo extends App {import scala.util.control._val Inner = new Breaksval Outer = new BreaksOuter.breakable {for (i <- 1 to 5) {Inner.breakable {for (j <- 'a' to 'e') {if (i == 1 && j == 'c') Inner.break else println(s"i: $i, j: $j")if (i == 2 && j == 'b') Outer.break}}}}
    }
    
  • 这个例子中,第一个if条件满足,会抛出一个异常然后被Inner.breakable捕获,外面的for循环继续。不过如果第二个if条件触发,控制流发送到Outer.breakable,然后两个循环都退出。运行结果如下:

    i: 1, j: a
    i: 1, j: b
    i: 2, j: a
    
  • 如果偏爱标记break使用相同的方法,下面演示只用一个break方法时的标记break使用

    import scala.util.control._val Exit = new Breaks
    Exit.breakable {for (j <- 'a' to 'e') {if (j == 'c') Exit.break else println(s"j: $j")}
    }
    

3.5.7 讨论

  • 如果不喜欢使用break和continue,还有其他方法可以解决这个问题。
  • 举例,需要添加猴子到桶中,直到桶装满了。可以利用一个简单的布尔测试来退出for循环

    var barrelIsFull = false
    for (monkey <- monkeyCollection if !barrelIsFull) {addMonkeyToBarrel(monkey)barrelIsFull = checkIfBarrelIsFull
    }
    
  • 另一个方法是在函数里进行计算,当达到所需条件时从函数里返回,下面的例子如果sum比limit大,sumToMax函数提前返回

    // calculate a sum of numbers, but limit it to a 'max' value
    def sumToMax(arr: Array[Int], limit: Int): Int = {var sum = 0for (i <- arr) {sum += iif (sum > limit) return limit}sum
    }
    val a = Array.range(0,10)
    println(sumToMax(a, 10))
    
  • 在函数式编程里通用方法是使用递归算法,下面演示阶乘函数:

    def factorial(n: Int): Int = {if (n == 1) 1else n * factorial(n - 1)
    }
    
  • 需要注意这个例子没有使用尾递归,所以不是最优方法,尤其起始值n特别大时。下面演示利用尾递归的更优方法。

    import scala.annotation.tailrecdef factorial(n: Int): Int = {@tailrec def factorialAcc(acc: Int, n: Int): Int = {if (n <= 1) accelse factorialAcc(n * acc, n - 1)}factorialAcc(1, n)
    }
    
  • 当确认算法是尾递归这种情况时可以使用@tailrec注解。如果你使用了这个注解但是你的算法不是尾递归,编译器会报错,比如在第一个factorial方法使用注解,会得到如下错误:

    Could not optimize @tailrec annotated method factorial: it contains a recursive call not in tail position
    
  • 查看更多

    Branching Statements
    Scala factorial on large numbers sometimes crashes and sometimes doesn’t


3.6 像三目运算符一样使用if结构

  • 问题: 使用Scala的if表达式如三目运算符一样更加简洁有效的解决问题

3.6.1 解决方案

  • 不像Java中,在Scala中有点小问题,因为Scala里没有特殊的三目运算符,只能使用if/else表达式:

    val absValue = if (a < 0) -a else aprintln(if (i == 0) "a" else "b")hash = hash * prime + (if (name == null) 0 else name.hashCode)
    

3.6.2 讨论

  • 更多例子如下,返回一个结果并且Scala语法使得代码更加简洁

    def abs(x: Int) = if (x >= 0) x else -xdef max(a: Int, b: Int) = if (a > b) a else bval c = if (a > b) a else b
    
  • 查看更多

    Equality, Relational, and Conditional Operators


3.7 像switch语句一样使用match表达式

  • 问题:需要创建一个基于整数的Java Switch语句,比如匹配一周中的每一天,一年中的每一月,等等其他整数map一个结果的情况。

3.7.1 解决方案

  • 使用Scala的match表达式,像Java Switch语句一样:

    // i is an integer
    i match {case 1 => println("January")case 2 => println("February")case 3 => println("March")case 4 => println("April")case 5 => println("May")case 6 => println("June")case 7 => println("July")case 8 => println("August")case 9 => println("September")case 10 => println("October")case 11 => println("November")case 12 => println("December")// catch the default with a variable so you can print itcase whoa => println("Unexpected case: " + whoa.toString)
    }
    
  • 从match表达式返回值的函数方法:

    val month = i match {case 1 => "January"case 2 => "February"case 3 => "March"case 4 => "April"case 5 => "May"case 6 => "June"case 7 => "July"case 8 => "August"case 9 => "September"case 10 => "October"case 11 => "November"case 12 => "December"case _ => "Invalid month" // the default, catch-all
    }
    

3.7.2 @switch注解

  • 如果使用简单match表达式,推荐使用@switch注解。在编译时如果switch不能编译成tableswitch或者lookupswitch时会提供一个警告。
  • 编译成tableswitch或者lookupswitch有更好的性能,因为它的结果是一个分支表而不是决策树。当给表达式一个给定值时,可以直接跳到结果处而不是执行完决策树。
  • 官方文档解释:如果在一个match表达式使用一个注解,编译器会确认这个match是否已经编译成tableswitch或者lookupswitch,如果编译成一系列条件表达式则会发出一个错误。

    // Version 1 - compiles to a tableswitch
    import scala.annotation.switchclass SwitchDemo {val i = 1val x = (i: @switch) match {case 1 => "One"case 2 => "Two"case _ => "Other"}}
    
  • 编译代码:

    $ scalac SwitchDemo.scala
    
  • 反汇编代码

    $ javap -c SwitchDemo//输出
    16: tableswitch{ //1 to 2
    1: 50;
    2: 45;
    default: 40 }
    
  • 输出是一个tableswitch,表明Scala可以优化match表达式成tableswitch
  • 然后进行小改动,使用变量代替整数2:

    import scala.annotation.switch// Version 2 - leads to a compiler warning
    class SwitchDemo {val i = 1val Two = 2 // addedval x = (i: @switch) match {case 1 => "One"case Two => "Two" // replaced the '2'case _ => "Other"}
    }//编译
    $ scalac SwitchDemo.scala
    SwitchDemo.scala:7: warning: could not emit switch for @switch annotated matchval x = (i: @switch) match {^
    one warning found
    
  • 这个警告是说这个匹配表达式既不能生成tableswitch也不能生成lookupswitch.
  • 在Scala In Depth指出必须满足下面几点才可以应用tableswitch优化
    • 匹配的值必须是已知整数
    • 匹配表达式必须简单,不能包含任何的类型检查,if语句,或者提取器
    • 编译时表达式必须有值
    • 有超过2个的case语句

3.7.3 讨论

  • 不止可以匹配整数:

    def getClassAsString(x: Any): String = x match {case s: String => s + " is a String"case i: Int => "Int"case f: Float => "Float"case l: List[_] => "List"case p: Person => "Person"case _ => "Unknown"
    }
    

3.7.4 处理默认的case

  • 如果不关注默认match的值,可以使用_

    case _ => println("Got a default match")
    
  • 相反,如果对默认match的值感兴趣,分配一个变量,然后可以在表达式右边使用变量:

    case default => println(default)
    
  • 使用default名称往往是最有意义的并导致代码可读。但是也可以使用任何合法的变量名称:

    case oops => println(oops)
    
  • 如果不处理默认的case会生成一个MatchError,比如下面:

    i match {case 0 => println("0 received")case 1 => println("1 is good, too")
    }//如果i的值超过0或1时,会抛出以下异常
    scala.MatchError: 42 (of class java.lang.Integer)at .<init>(<console>:9)at .<clinit>(<console>)much more error output here ...
    

3.7.5 是否真的需要switch语句

  • 如果有一个map的数据结构,并不需要一个switch语句:

    val monthNumberToName = Map(1 -> "January",2 -> "February",3 -> "March",4 -> "April",5 -> "May",6 -> "June",7 -> "July",8 -> "August",9 -> "September",10 -> "October",11 -> "November",12 -> "December"
    )val monthName = monthNumberToName(4)
    println(monthName) // prints "April"
    
  • 查看更多

    The @switch annotation documentation
    Compiling Switches:讨论tableswitch和lookupswitch
    Difference between JVM’s LookupSwitch and TableSwitch?

Scala Cookbook读书笔记 Chapter 3.Control Structures 第一部分相关推荐

  1. 《C++捷径教程》读书笔记--Chapter 10--结构与联合

    //--<C++捷径教程>读书笔记--Chapter 10--结构与联合 //--Chapter 10--结构与联合 //--11/24/2005 Thurs. //--Computer ...

  2. 《Programming in Scala》读书笔记(持续更新) - passover的个人空间 - DOIT博客 - 多易网...

    <Programming in Scala>读书笔记(持续更新) - passover的个人空间 - DOIT博客 - 多易网 <Programming in Scala>读书 ...

  3. 《C++捷径教程》读书笔记--Chapter 16--模板(完结)

    //--<C++捷径教程>读书笔记--Chapter 16--模板(完结) //--Chapter 16--模板 //--04/16/2006 Sun. //--Computer Lab ...

  4. 《C++捷径教程》读书笔记--Chapter 14--继承(完结)

    //--<C++捷径教程>读书笔记--Chapter 14--继承(完结) //--Chapter 14--继承 //--04/14/2006 Friday //--Computer La ...

  5. 读书笔记: Cartesian Impedance Control of Redundant and Flexible-Joint Robots, Section 2

    读书笔记: Cartesian Impedance Control, Section 2 Section 2 柔性关节机器人建模 2.1 运动学 2.2 柔性关节机器人动力学模型 2.2.1 Comp ...

  6. 【SQL.Cookbook读书笔记】——1检索记录

    SQL.Cookbook读书笔记 前言 1检索记录 1.1从表中检索所有行和列 1.2从表中检索部分行(where) 1.3查找满足多个条件的行(where.and.or) 1.4从表中检索部分列 1 ...

  7. [The Path to QUANT] 《Volatility Trading》by Euan Sinclair 读书笔记 Chapter 3

    <Volatility Trading> by Euan Sinclair Chapter 3 收益率和波动率的典型事实 典型事实列表 波动率并非常数 收益率分布 成交量和波动率 波动率分 ...

  8. [The Path to QUANT] 《Volatility Trading》by Euan Sinclair 读书笔记 Chapter 4

    <Volatility Trading> by Euan Sinclair Chapter 4 预测波动率 波动率是否可以被预测? 无摩擦交易市场(交易费用为零) 信息有效(完美信息流) ...

  9. Flex CookBook 读书笔记 第一部分

    定义数组和对象 可以通过ActionScript或者在Mxml中定义 <mx:Array> <mx:String>flex</mx:String> <mx:S ...

最新文章

  1. 蒙特卡洛模拟预测股票_使用蒙特卡洛模拟来预测极端天气事件
  2. docker 学习笔记一(教程) 快速上手
  3. 开发小计之判断输入字符串类型(正则表达式)
  4. jqGrid 操作一些总结(二)
  5. Hive数仓基本概念介绍
  6. Android Okhttp 配置HTTPS
  7. uml通信图画法_UML9种图的画法
  8. 手机输入法哪家好用?用户目前最喜爱这4款,有你正在使用的吗
  9. 真切还是虚无?宇宙可能是一个假真空气泡
  10. 《算法导论》第十二章——二叉搜索树
  11. 解决Google Drive 大文件下载过程中中途失败问题
  12. 用计算机测缘分,用两人的姓名测姻缘 免费测试两个人的缘分
  13. 杭漂多年是时候画个句号呢
  14. 基于光流传感器定位和导航的自主飞行无人机
  15. Nestjs模块机制的概念和实现原理
  16. win10系统如何格式化
  17. 计算机应用基础教学进度表,《计算机应用基础》教学计划及教学进度
  18. 在word中填加标题四的方法
  19. 网络黑客攻防学习平台之基础关第十一题
  20. 【分享故事会】互联网之编程开发的道道

热门文章

  1. form-login属性详解
  2. “请不要在虚拟机中打开”解决方法
  3. mysqlin会使用索引吗
  4. 运放放大倍数计算公式_电源经典运放电路,加法器,减法器,同向放大器,反向放大器...
  5. CVPR_2021_Fast-GANFIT: Generative Adversarial Networkfor High Fidelity 3D Face Reconstruction
  6. IDEA学生免费申请教程
  7. 台式机如何通过无线网卡释放热点?
  8. Person ReID最新论文推荐
  9. coreldraw x8里线段显示尺寸_CorelDRAW X8如何修改标尺单位
  10. 吴恩达deeplearning.ai深度学习课程空白作业