Scala2.8探秘之for表达式

  虽然Scala2.8还在持续跳票中,但目前[url=http://www.scala-lang.org/node/212/distributions]Nightly Build[/url]版本的可用性已经很高了,其中Scala2.8中主要特性都已经实现。毫无疑问,Scala2.8的发布将会是Scala发展中的一个重大里程碑。在这个版本中,不仅包括了许多Scala社区期待已久的特性,如命名参数、类型特殊化等等,详细的信息可以参看[url]http://eastsun.iteye.com/blog/373710[/url];而且包含了一些对之前Scala中设计不合理的地方的改进,例如Scala中对String以及数组的处理,在之前的版本中Scala编译器在编译的时候对这两种类型进行了一些比较特殊(魔法)的处理,这样做虽然某些程度上使得这两种类型在Scala中更加易用,但同时也破坏了Scala中的一致性,并随之产生了一些离奇的问题。举个例子,在Scala2.7.7 final中我们可以看到如下结果:
[code]
//Scala2.7.7 final
scala> val array = Array("String Array")
array: Array[java.lang.String] = Array(String Array)

scala> println(array.toString())
Array(String Array)

scala> println(array)
[Ljava.lang.String;@139491b

scala> "WOW" == "WOW".reverse
res4: Boolean = false

scala> "abcdefg" map { _.toUpperCase }
res5: Seq[Char] = ArrayBufferRO(A, B, C, D, E, F, G) //注意,得到的是个Seq[Char]而不是String
[/code]
  显然这样的运行结果有违我们的直觉,即使是对Scala有一定了解的人也未必能马上明白其中的奥妙。
  在Scala2.8中,这些问题都得到了一定的解决——可能有些解决方式会让你觉得退步了,但是保持了Scala的一致性,并且消除了编译器在背后做的那些魔法,使事情变得简单——虽然这样破坏了Scala的向后兼容性,但我认为这样做事非常值得的:这为Scala成为一门成功的语言垫下了基础。下面我们看看在Scala 2.8.0.r20117-b20091213020323中上面代码的运行结果:
[code]
scala> val array = Array("String Array")
array: Array[java.lang.String] = Array(String Array)

scala> println(array.toString())
[Ljava.lang.String;@335053

scala> println(array)
[Ljava.lang.String;@335053

scala> "WOW" == "WOW".reverse
res2: Boolean = true

scala> "abcdefg" map { _.toUpperCase }
res3: String = ABCDEFG
[/code]
  可以看到,运行结果就如我们所预想的那样——固然其中数组的toString结果变得丑陋了,和Java中一样丑陋,但保持一致了。
  OK,String与数组的讨论就此为止,以后如果有时间我再来详细解释一下其背后的故事;现在我们转向本文要讨论的东东:Scala中的for表达式。注意:在本文中使用了两种不同的Scala版本:Scala2.7.7final与2.8.0.r20117-b20091213020323进行对比。
[b]
[size=large]1.Scala2.8之前的for表达式[/size][/b]
  在Scala中,通常有以下几种使用方式:
[code]
for (p <- e) e'
for (p <- e if g) e'
for (p <- e; p' <- e' ...) e''
[/code]
以及相应的
[code]
for (p <- e) yield e'
for (p <- e if g) yield e'
for (p <- e; p' <- e' ...) yield e''
[/code]
其中p,p'为Scala中的Pattern;e,e',e''为表达式;g为Boolean表达式。
  根据《The Scala Language Specification Version 2.7》,上面的for表达式将在编译阶段展开为下面的形式(没有考虑p为比较复杂的Pattern时的情形):
[code]
for (p <- e) e' => e.foreach { case p => e' }
for (p <- e if g) e' => for (p <- e.filter{ (x1,...,xn) => g }) e' => ..
for (p <- e; p' <- e' ...) e'' => e.foreach{ case p => for (p' <- e' ...) e'' }
[/code]
以及相应的
[code]
for (p <- e) yield e' => e.map { case p => e' }
for (p <- e if g) yield e' => for (p <- e.filter{ (x1,...,xn) => g }) yield e'
for (p <- e; p' <- e' ...) yield e'' => e.flatmap { case p => for (p' <- e' ...) yield e'' }
[/code]
  注意的是,这个转换发生在类型检查之前。也就是说,对map,filter,flatMap以及foreach这四个方法的方法签名没有任何其它限制,只需要满足展开后for语句的类型检查。通常情况下,对于一个具有类型参数A的类C——一般表示某种数据结构(集合)——下面的定义方式是比较自然的:
[code]
class C[A] {
def map[B](f: A => B): C[B]
def flatMap[B](f: A => C[B]): C[B]
def filter(p: A => Boolean): C[A]
def foreach(b: A => Unit): Unit
}[/code]
  相对Java1.5中的for语句,Scala的实现更加灵活,并且以一种轻量级的方式实现了[url=http://en.wikipedia.org/wiki/List_comprehension]List comprehension[/url]。举个例子,下面几行代码实现了求一个List的全排列:
[code]
scala> def perm[T](ls: List[T]): List[List[T]] = ls match {
| case Nil => List(Nil)
| case xs => for(x <- xs;ys <- perm(xs-x)) yield x::ys
| }
perm: [T](List[T])List[List[T]]

scala> perm(1::2::3::Nil)
res2: List[List[Int]] = List(List(1, 2, 3), List(1, 3, 2), List(2, 1, 3),
List(2, 3, 1), List(3, 1, 2), List(3, 2, 1))
[/code]
  但是这个转换规则还不甚完美。当转换后的表达式含有filter方法的时候,会产生几个问题。
[b][color=red](a)性能问题[/color][/b]
  以一个简单的问题为例:[color=blue]求1~999中所有偶数之和。[/color]
  下面是两段类似的解决代码:
[code]
val set = 1 until 1000
var sum = 0
for(num <- set;if(num%2 == 0)) sum += num
[/code]
或者把if语句移到括号外面:
[code]
val set = 1 until 1000
var sum = 0
for(num <- set) if(num%2 == 0) sum += num
[/code]
  这两段代码功能上应该是等价的,但是运行效率如何呢?下面首先写一个粗略的测试函数:
[code]
/**
计算count次调用call所需的时间,单位:毫秒
*/
def time(call : => Unit,count: Int): Long = {
var cnt = count
val start = System.currentTimeMillis
while(cnt > 0) {
call
cnt -= 1
}
System.currentTimeMillis - start
}
[/code]
  先在Scala2.7.7final中将每段代码各运行十万次:
[code]
scala> val set = 1 until 1000
set: Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...

scala> time({
| var sum = 0
| for(num <- set;if(num%2 == 0)) sum += num
| },100000)
res3: Long = 47390

scala>

scala> time({
| var sum = 0
| for(num <- set) if(num%2 == 0) sum += num
| },100000)
res4: Long = 3344

scala>
[/code]
  测试结果很出乎意料:两段类似的代码,性能竟相差一个数量级!
  之所以会有这么大的差异,根据上述的转换规则,第一段代码将会转换为下面的实际执行代码:
[code]
val set = 1 until 1000
var sum = 0
set.filter{ num => num%2 == 0) }.foreach{ case num => sum += num }
[/code]
  而第二段代码实际执行的是:
[code]
val set = 1 until 1000
var sum = 0
set.foreach{ case num => if(num%2 == 0) sum += num }
[/code]
  相对而言,第一段代码会调用filter方法,创建一个新的集合类,而这个集合类包含了1~999中所有的偶数。显然这个过程是比较昂贵的,也是不必要的。

[b][color=red](b)运行顺序[/color][/b]
  以
[code]for (p <- e if g) e'[/code]
为例,实际运行的代码为:
[code]
e.filter{ (x1,...,xn) => g }.foreach{ case p => e'}
[/code]
  可以看到,虽然直观上if g与e'在遍历的时候应该是依次循环执行;但事实上转换后if g整体先于e'执行。当g与e'中同时包含一个变量v,并且在g中对变量v进行改动时,实际运行结果可能和我们所预想的不一致。可能问题描述的不是很清楚,下面引用fineqtbull同学在[url=http://scalagroup.group.iteye.com/group/blog/481804]for语句中内嵌if语句的副作用[/url]一文中的代码作为例子来说明:实现compress方法,其功能是将一个list中连续相同的元素删减至一个。比如compress(List(1,1,2,3,3,1,1,4)) == List(1,2,3,1,4),下面是两段类似的实现代码,咋一看都没问题,但运行结果却不一样。
[code]
Welcome to Scala version 2.7.7.final (Java HotSpot(TM) Client VM, Java 1.6.0_17).

scala> def compress1[T](ls: List[T]): List[T] = {
| var res = List(ls.first)
| for(x <- ls) if(x != res.last) res = res:::List(x)
| res
| }
compress1: [T](List[T])List[T]

scala> def compress2[T](ls: List[T]): List[T] = {
| var res = List(ls.first)
| for(x <- ls;if(x != res.last)) res = res:::List(x)
| res
| }
compress2: [T](List[T])List[T]

scala> compress1(List(1,1,2,3,3,1,1,4))
res0: List[Int] = List(1, 2, 3, 1, 4)

scala> compress2(List(1,1,2,3,3,1,1,4))
res1: List[Int] = List(1, 2, 3, 3, 4)

scala>
[/code]
  有了之前的说明,我们不难发现其原因所在。但这样的结果显然违反了C/Java中习惯用法,很容易让一个刚接触Scala的人产生困惑。
[size=large]
[b]2.Scala2.8中的for表达式[/size][/b]
  刚才已经提到了Scala2.8之前for表达式所存在的两个问题,那么在Scala2.8中这两个问题有没有得到解决呢?下面将之前的代码在2.8.0.r20117-b20091213020323重新运行一次试试:
[code]
Welcome to Scala version 2.8.0.r20117-b20091213020323 (Java HotSpot(TM) Client VM, Java 1.6.0_17).

scala> def time(call : => Unit,count: Int): Long = {
| var cnt = count
| val start = System.currentTimeMillis
| while(cnt > 0) {
| call
| cnt -= 1
| }
| System.currentTimeMillis - start
| }
time: (call: => Unit,count: Int)Long

scala> val set = 1 until 1000
set: scala.collection.immutable.Range ...

scala> time({
| var sum = 0
| for(num <- set;if(num%2 == 0)) sum += num
| },100000)
res0: Long = 6906

scala> time({
| var sum = 0
| for(num <- set) if(num%2 == 0) sum += num
| },100000)
res1: Long = 4312

scala> def compress1[T](ls: List[T]): List[T] = {
| var res = List(ls.first)
| for(x <- ls) if(x != res.last) res = res:::List(x)
| res
| }
compress1: [T](ls: List[T])List[T]

scala> def compress2[T](ls: List[T]): List[T] = {
| var res = List(ls.first)
| for(x <- ls;if(x != res.last)) res = res:::List(x)
| res
| }
compress2: [T](ls: List[T])List[T]

scala> compress1(List(1,1,2,3,3,1,1,4))
res2: List[Int] = List(1, 2, 3, 1, 4)

scala> compress2(List(1,1,2,3,3,1,1,4))
res3: List[Int] = List(1, 2, 3, 1, 4)

scala>
[/code]
  可以看到Scala2.8中已经很好的解决了这两个问题。对于一门语言,要想对已经存在的问题进行改进是很困难的,因为首先这些改进要尽可能少的影响已经存在的旧有代码,另一方面不能带来新的问题。幸运的是,Martin想到了一个简单而优雅的方法成功做到了这些。下面简单的叙述一下Martin的解决方法,感兴趣的同学可以去看Martin的原文[url=http://old.nabble.com/Rethinking-filter-to25906315.html#a25923142]Rethinking filter[/url]。
  首先,Martin引入了一个新的方法withFilter,这个方法与filter方法一样以一个条件函数A => Boolean作为参数。与filter方法不同的是,withFilter方法是lazy的。它并不会创建一个新的包含符合条件的元素所组成的集合类,而是返回一个代理类WithFilter,这个类具有foreach、map、flatMap以及withFilter等方法,并且所有这些方法的调用是与原来条件组合的结果。下面是TraversableLike中WithFilter的实现,Scala2.8中所有的集合类都继承了TraversableLike:
[code]
class WithFilter(p: A => Boolean) {

/** Builds a new collection by applying a function to all elements of the
* outer $coll containing this `WithFilter` instance that satisfy predicate `p`.
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
* @tparam That $thatinfo
* @param bf $bfinfo
* @return a new collection of type `That` resulting from applying the given function
* `f` to each element of the outer $coll that satisfies predicate `p`
* and collecting the results.
*
* @usecase def map[B](f: A => B): $Coll[B]
*
* @return a new $coll resulting from applying the given function
* `f` to each element of the outer $coll that satisfies predicate `p`
* and collecting the results.
*/
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
for (x <- self)
if (p(x)) b += f(x)
b.result
}

/** Builds a new collection by applying a function to all elements of the
* outer $coll containing this `WithFilter` instance that satisfy predicate `p` and concatenating the results.
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
* @tparam That $thatinfo
* @param bf $bfinfo
* @return a new collection of type `That` resulting from applying the given collection-valued function
* `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
*
* @usecase def flatMap[B](f: A => Traversable[B]): $Coll[B]
*
* @return a new $coll resulting from applying the given collection-valued function
* `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
*/
def flatMap[B, That](f: A => Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
for (x <- self)
if (p(x)) b ++= f(x)
b.result
}

/** Applies a function `f` to all elements of the outer $coll containing this `WithFilter` instance
* that satisfy predicate `p`.
*
* @param f the function that is applied for its side-effect to every element.
* The result of function `f` is discarded.
*
* @tparam U the type parameter describing the result of function `f`.
* This result will always be ignored. Typically `U` is `Unit`,
* but this is not necessary.
*
* @usecase def foreach(f: A => Unit): Unit
*/
def foreach[U](f: A => U): Unit =
for (x <- self)
if (p(x)) f(x)

/** Further refines the filter for this $coll.
*
* @param q the predicate used to test elements.
* @return an object of class `WithFilter`, which supports
* `map`, `flatMap`, `foreach`, and `withFilter` operations.
* All these operations apply to those elements of this $coll which
* satify the predicate `q` in addition to the predicate `p`.
*/
def withFilter(q: A => Boolean): WithFilter =
new WithFilter(x => p(x) && q(x))
}
}[/code]
  在Scala2.8中,for表达式的转换方式大体保持不变,只是将以前使用filter的地方全部替换为withFilter方法。

[b][size=large]结语[/size][/b]:可以看到Scala2.8成功解决了之前Scala中存在的一些问题,使得Scala语言变得更加优雅、强大。你还在等待Java7的闭包吗?赶紧去尝试Scala2.8吧^_^
Citrix NetScaler-A10应用交付实战指南:负载均衡+SSL卸载+CLI命令 企业级 ADC(NetScaler VPX/A10 vThunder)完整教程,覆盖部署、负载均衡、SSL 卸载、内容交换、CLI 命令。掌握企业级应用交付核心技术,概念与 F5 相通。 立即下载

相关推荐

如何实现高校科技成果快速转化?.docx

如何实现高校科技成果快速转化?

scala2.72.8的一些方法变化

Scala2.8的Beta终于发布了,变化可是真大啊,除了[url=http://www.scala-lang.org/node/4587]官方提到[/url]的外,在一些Object的方法也有不少的小改动,在此将碰到的简单罗列一下: [list] [*]Source.getLines,增加了缺省换行的参数,因此调用需要加上括号,.getLines() [*]Array更像Java的Ar...

lovec的专栏 176

vue便利购超市库存信息管理平台(代码+数据库+LW)

摘要 针对便利购超市传统库存管理中人工操作效率低、数据同步滞后、权限边界模糊、流程不规范等问题,为实现库存管理的数字化、规范化与智能化,提升多角色协同效率,本文设计并实现了一套适配中小型超市实际业务的库存信息管理平台。研究以问题为导向,遵循调研分析 - 设计开发 - 测试优化的软件开发流程,先通过文献研究与实地调研梳理核心技术要点与业务需求,明确管理员、库管、一线员工三类角色的功能边界;再基于 Vue+Spring Boot+MyBatis 技术栈搭建前后端分离架构,结合 RBAC 角色权限模型与数据库第三范式完成系统整体设计,涵盖需求分析、架构设计、功能模块设计、接口与权限控制设计、界面原型设计等环节;随后完成平台前后端开发实现,实现商品及类别管理、库存预警、出入库与报损管理、全局库存管控等九大核心功能,同时针对开发中的权限控制、数据一致性、接口交互等问题提出针对性解决策略;最后通过功能、性能、兼容性多维度测试验证系统有效性。测试结果表明,该平台实现了库存管理全流程的线上化,可实现多角色权限的精细化管控、库存数据的实时同步与预警信息的即时推送,有效解决了传统库存管理的痛点,提升了超市库存管理的效率与精准度。系统兼具良好的稳定性、易用性与可扩展性,可为中小型零售超市的库存数字化管理提供技术支撑与实践参考,后续可进一步拓展数据分析、智能补货等功能,提升平台的智能化水平。 关键词:库存预警;超市;MyBatis

Scala入门】Scala中的For循环

import scala.collection.immutable /** * For循环 */ object ForDemo { def main(args: Array[String]): Unit = { //定义一个数组变量,to后的第一个参数为末位置(包含该值),第二个参数为步长(负数为递减) val arr1 = 1 to (10, 2) val ...

fuyun6363的博客 655

scala函数 for循环

scala中使用def定义一个函数: 无返回值的函数 def add(a:Int , b:Int){        println(a + b)      } 有返回值的函数 def add(a:Int , b:Int) :Int = { //需要有具体返回值时要添加“=”        a + b;  //scala默认返回最后一行的值      } for循环

qa38113202的博客 463

scala表达式

Scala中的yield的主要作用是记住每次迭代中的有关值,并逐一存入到一个数组中。- 表达式一般是一个语句块,可包含一条或者多条语句,多条语句使用“{}”包含,语句间以“;1.表达式有返回值,语句被执行。表达式一般是一个语句块,执行后,返回一个值。if-else表达式有值,这个值就是跟在if或者else之后的表达式的值。在Scala中有for循环和while循环,用for循环比较多。说明:当条件表达式为ture 时,就会执行 { } 的代码。说明:当条件表达式成立,即执行代码块1,否则执行代码块2.

HYSliuliuliu的博客 9817

Scala教程(二十)For循环模式匹配与表达式

For循环模式匹配与表达式; 1.1 模式匹配下的For循环; 1.2 模式匹配下的赋值语句; 1.3 模式匹配下的提取器; 1.4 ScalaFor表达式; 1.5 For表达式查询过滤;

yuan_xw的专栏 2350

Scala语法(scala条件表达式__for循环__while循环)

条件表达式 条件表达式就是if表达式scala条件表达式的语法和Java一样。 有返回值的if 参考代码: scala> val sex = "male" sex: String = male ​ scala> val result = if(sex == "male") 1 else 0 result: Int = 1 与Java不一样的是 在scala中,条件表达式也是有返回...

写的不好之处,请指教 5497

ScalaJava 8中Lambda表达式这么用,你知道么

最近几年Lambda表达式风靡于编程界. 很多现代编程语言都把它作为函数式编程的基本组成部分. 基于JVM的编程语言如Scala,Groovy还有Clojure把它们作为关键部分集成在语言中.现在Java8也加入了它们的行列. 有趣的是,对于JVM来说,Lambda表达式是完全不可见的,并没有匿名函数和Lamada表达式的概念,它只知道字节码是严格面向对象规范的.它取决于语言的作者和它的编译器在规范限制内创造出更新,更高级的语言元素. 我们第一次接触它是在我们要给Takipi添加Scala支持的时...

weixin_46577306的博客 1083

Scala语法介绍():scala条件表达式-for循环-while循环

条件表达式 条件表达式就是if表达式scala条件表达式的语法和Java一样。 有返回值的if 参考代码: scala> val sex = "male" sex: String = male ​ scala> val result = if(sex == "male") 1 else 0 result: Int = 1 与Java不一样的是 在scala中,条件表达式也是有返回...

4749

Scala 2.12将只支持Java 8

根据近期Scala路线图所公布的信息来看,Scala从版本2.12开始,只能运行在Java 8及之后的版本上。InfoQ找到了Adriaan Moors(Typesafe的Scala技术主管)和Json Zaugg(Typesafe工程师),了解到更多关于这个改动的内容,以及Scala将如何利用Java 8的lambda表达式的细节。\u0026#xD;\u0026#xD;InfoQ:做出这个改动...

cpongo011702 1075

故障重构改进深度优先搜索算法配合二进制粒子群的配电网故障恢复重构研究(Matlab代码实现)

内容概要:本文研究了改进深度优先搜索算法与二进制粒子群优化算法相结合在配电网故障恢复重构中的应用,旨在提升故障后网络重构的效率与供电可靠性。通过引入改进的深度优先搜索算法高效生成满足辐射状约束的可行拓扑结构,并结合二进制粒子群算法进行全局优化,实现对开关操作序列的智能决策。文中系统阐述了两种算法的协同机制、适应度函数构建、配电网约束处理(如潮流平衡、电压限值、容量限制)以及孤岛与环网的规避策略,提出了一套完整的故障恢复重构流程。基于Matlab平台的仿真验证表明,该方法能在较短时间内找到高质量的恢复方案,有效恢复失电负荷,避免不合理的网络结构,具有较强的实用性和鲁棒性。; 适合人群:具备电力系统分析基础和Matlab编程能力,从事智能电网、配电自动化、故障诊断与恢复、电力系统优化等方向的科研人员及工程技术人员。; 使用场景及目标:①应对配电网突发故障,快速制定最优网络重构方案以最大化恢复供电范围;②优化故障后开关操作策略,降低停电损失和运行风险;③为配电管理系统(DMS)和自愈控制系统提供高效的算法支撑;④研究启发式算法与图搜索算法在复杂电力网络优化中的融合应用; 阅读建议:建议读者结合Matlab代码深入理解算法实现细节,重点关注深度优先搜索在拓扑可行性校验中的作用以及粒子群算法在离散空间优化中的编码与更新策略,可通过调整网络模型、故障场景和算法参数进行对比实验,以全面掌握其性能特点与适用边界。

政府科技管理部门如何优化科技创新服务体系?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

政府科技管理部门如何提升科技成果转化效率?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

SCI复现动态规划自适应最优控制在系统动力学完全未知的连续时间线性系统的应用(Matlab代码实现)

内容概要:本文围绕“自适应最优控制在系统动力学完全未知的连续时间线性系统中的应用”展开,基于动态规划理论,提出了一种无需先验系统模型的数据驱动型自适应最优控制方法,并通过Matlab代码实现完成算法验证。文中系统阐述了在缺乏精确系统动态方程的前提下,如何融合强化学习中的策略迭代与值迭代思想,利用在线采集的状态数据逐步逼近哈密尔顿-雅克比-贝尔曼(HJB)方程的最优解,从而实现对无限时域线性二次调节器(LQR)问题的有效求解。该方法突破了传统最优控制对精确数学模型的依赖,具备良好的鲁棒性与工程适用性,特别适用于智能电网、机器人控制、飞行器导航等建模困难或存在模型不确定性的复杂系统。文档不仅包含详尽的理论推导与算法流程,还提供了完整的Matlab仿真实现代码及丰富的拓展科研资源,涵盖智能优化、机器学习、信号处理等多个交叉领域,强调“借力科研工具”以提升研究效率与创新能力。; 适合人群:具备现代控制理论基础和Matlab编程能力,从事自动化、控制工程、人工智能或相关方向的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究数据驱动的自适应动态规划(ADP)与最优控制算法的设计与实现;②应用于系统建模困难或参数时变的实际控制系统中,解决模型不确定性带来的控制难题;③复现高水平SCI论文中的先进控制策略,提升科研创新能力与算法实践水平。; 阅读建议:此资源以Matlab代码实现为核心,强调理论分析与仿真实践深度融合,建议读者按照文档目录循序渐进地学习,重点关注算法原理推导、代码实现细节与参数调优过程,并充分利用所提供的网盘资源进行动手复现与拓展研究,以深化对自适应最优控制机制的理解。

上一篇: Sun在Devoxx2009上宣布Java7中将加入FCM(闭包)
下一篇: Projecteuler 169
JavaSxy
博客等级 码龄20年 1粉丝 25原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值