Scala系列-4、scala中特质、柯里化、闭包等
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
传送门:大数据系列文章目录
目录
- scala中特质
- 特质作为接口使用
- 特质中放置非抽象的成员
- 特质的模板操作
- 特质的混入对象操作
- 特质的执行链条
- 特质的构造执行流程
- 特质继承class
- 样例类
- 样例对象
- scala中模式匹配操作
- Option类型
- scala中偏函数
- scala中正则表达式操作
- scala中异常处理
- 柯里化
- 闭包
- 隐式转换和隐式参数
scala中特质
scala中没有Java中的接口(interface),替代的概念是——特质
语法
trait 名称 {// 抽象字段// 抽象方法
}继承特质:
class 类 extends 特质1 with 特质2 {// 字段实现// 方法实现
}说明:
- 特质是scala中代码复用的基础单元
- 它可以将方法和字段定义封装起来,然后添加到类中
- 与类继承不一样的是,类继承要求每个类都只能继承一个超类,而一个类可以添加任意数量的特质。
- 特质的定义和抽象类的定义很像,但它是使用trait关键字
- 使用extends来继承trait(scala不论是类还是特质,都是使用extends关键字)
- 如果要继承多个trait,则使用with关键字
特质作为接口使用
创建特质
package com.leetrait Person {//抽象成员变量val name:Stringval age: Intvar address:Stringvar birthday:String// 抽象的方法def work()def eat()
}
继承特质
package com.leeclass Teacher extends Person {override val name: String = "小胖"override val age: Int = 45override var address: String = "北海"override var birthday: String = "1980-10-05"override def work(): Unit = {println("开始工作....")}override def eat(): Unit = {println("小胖开始吃饭....")}
}
相关的操作
package com.leeobject MainTest01 {def main(args: Array[String]): Unit = {val teacher = new Teacherteacher.work()println(teacher.age)}}
特质中放置非抽象的成员
创建特质
package com.leetrait Person {//抽象成员变量val name:Stringval age: Intvar address:Stringvar birthday:String// 定义一个非抽象的成员变量val sex:String = "男"// 抽象的方法def work()def eat()// 定义非抽象的方法def run(): Unit ={println("人人都需要跑步 健身....")}}
特质的模板操作
示例: 模拟一个日志输出到不同地方的操作
创建特质: 指定输出的内容 , 具体输出位置 并不清楚, 采用抽象
package com.leetrait Logger {def msg():Stringdef info() = println("输出info日志:"+msg())def waring() = println("输出警告日志:"+msg())def error() = println("输出错误日志:"+msg())
}
继承特质: 指定输出的地方
package com.leeclass ConsoleLogger extends Logger {override def msg() = "控制台"}
使用操作
package com.leeobject MainTest01 {def main(args: Array[String]): Unit = {val consoleLogger = new ConsoleLoggerconsoleLogger.info()}}
特质的混入对象操作
作用: 可以增强对象的功能
格式:
new 类 with 特质
操作
创建特质
package com.leetrait Person {val name:String = "李哥"def study() = {println(name + ":爱学习....")}
}
使用特质混入
package com.leeobject MainTest01 {def main(args: Array[String]): Unit = {// 对象混入特质: 提升当前这个对象的功能val tearcher = new Tearcher with Persontearcher.study()}
}
特质的执行链条
说明: 当一个类继承了多个特质, 而多个特质又有相同的方法, 并每个方法都调用父类的方法, 此时执行顺序为从右往左依次执行
演示操作
代码演示
trait HandlerTrait {def handle(data:String) = println("处理数据...")
}trait DataValidHanlderTrait extends HandlerTrait {override def handle(data:String): Unit = {println("验证数据...")super.handle(data)}
}trait SignatureValidHandlerTrait extends HandlerTrait {override def handle(data: String): Unit = {println("校验签名...")super.handle(data)}
}class PayService extends DataValidHanlderTrait with SignatureValidHandlerTrait {override def handle(data: String): Unit = {println("准备支付...")super.handle(data)}
}def main(args: Array[String]): Unit = {val service = new PayServiceservice.handle("支付参数")
}// 程序运行输出如下:
// 准备支付...
// 检查签名...
// 验证数据...
// 处理数据...
特质的构造执行流程
说明: 当类继承了多个特质后, 而多个特质中都有构造方法, 此时执行的顺序为:
- trait也有构造代码,但和类不一样,特质不能有构造器参数
- 每个特质只有
一个无参数
的构造器。 - 一个类继承另一个类、以及多个trait,当创建该类的实例时,它的构造顺序如下
- 执行父类的构造器
从左到右
依次执行trait的构造器- 如果trait有父trait,先构造父trait,如果多个trait有同样的父trait,则只初始化一次
- 执行子类构造器
相关的操作:
创建多个特质
package com.leetrait T1 {println("这是T1的特质 构造方法.....")
}package com.leetrait T2 extends T1{println("这是T2的特质 构造方法.....")
}package com.leetrait T3 extends T1{println("这是T3的特质 构造方法.....")
}package com.leetrait T4 extends T3{println("这是T4的特质 构造方法.....")
}
创建一个普通类 继承特质
package com.leeclass C5 extends T4 with T3 with T2 with T1{println("这是 C5的构造方法")
}
调用使用
package com.leeobject MainTest01 {def main(args: Array[String]): Unit = {new C5}
}
特质继承class
trait也可以继承class的。特质会将class中的成员都继承下来。
相关的操作:
创建一个类
package com.leeclass C1 {val name:String = "张三"def eat() = {println(name+":吃东西")}
}
创建一个特质
package com.leetrait T1 extends C1{}
创建测试:
package com.leeobject MainTest01 {def main(args: Array[String]): Unit = {val c = new C1c.eat()}}
样例类
什么是样例类? 样例类主要的作用是为了进行封装数据的操作, 类似于java中实体类(POJO JavaBean)
如何实现一个样例类:
case class 样例类名([var/val] 成员变量名1:类型1, 成员变量名2:类型2, 成员变量名3:类型3)使用说明:1) 在定义样例类的时候,成员变量是不需要进行初始化的操作2) 成员变量可使用val 或者 var修饰, 默认采用 val, 所以在定义的时候, 是可以省略的3) 如果使用val来定义变量, 此变量在创建样例类对象后, 其变量只能被赋值一次
需求
- 定义一个Person样例类,包含姓名和年龄成员变量
- 创建样例类的对象实例(“张三”、20),并打印它
object Demo01 {/*需求- 定义一个Person样例类,包含姓名和年龄成员变量- 创建样例类的对象实例("张三"、20),并打印它说明:1) 在样例类中, 默认重写toString方法2) 为成员变量自动实现 get 和 set 方法3) 在样例类自动实现 apply方法, 构建样例类对象的时候, 可以不写new的*/case class Person(name:String , age:Int)def main(args: Array[String]): Unit = {val person:Person = new Person("张三",20)println(person) // Person(张三,20)// 创建person对象:val person1:Person = Person("张三",20)println(person1)}}
当我们定义一个样例类,编译器自动帮助我们实现了以下几个有用的方法:
- apply方法
- toString方法
- equals方法
- hashCode方法
- copy方法
样例对象
是单例的, 只有一个示例对象, 一般将样例对象, 看做是java中一种用于定义常量的操作(枚举)
格式:
case object 样例对象名
需求说明
- 定义一个性别Sex枚举,它只有两个实例(男性——Male、女性——Female)
- 创建一个Person类,它有两个成员(姓名、性别)
- 创建两个Person对象(“张三”、男性)、(“李四”、“女”)
package com.leeobject Demo02 {/*需求说明- 定义一个性别Sex枚举,它只有两个实例(男性——Male、女性——Female)- 创建一个Person类,它有两个成员(姓名、性别)- 创建两个Person对象("张三"、男性)、("李四"、"女")*/trait Sexcase object Male extends Sexcase object Female extends Sexcase class Person(name:String ,sex:Sex)def main(args: Array[String]): Unit = {val person1 = Person("张三",Male)val person2 = Person("李四",Female)println(person1)}
}
scala中模式匹配操作
scala中模式匹配的操作, 类似于java中switch语句, 但是要比java的switch语句要强大的多, 在java的switch语句仅支持一些基本数据类型
格式:
变量 match {case "常量1" => 表达式1case "常量2" => 表达式2case "常量3" => 表达式3case _ => 表达式4 // 默认配
}
相关的操作
package com.leeclass MatchDemo01 {}import scala.io.StdIn
import scala.util.Randomobject CaseDemo {def main(args: Array[String]): Unit = {//1.匹配字符串/数字....println("---1.匹配字符串---")val arr1 = Array("hadoop","spark")var name = arr1(Random.nextInt(arr1.length)) //随机生成一个[0 ~ arr1.length)范围的数字//name = "xxx"println(name)/*if( name == "hadoop"){println("hadoop是大数据中离线存储和计算的框架....")}else if (name == "spark") {println( "spark是大数据中用于计算的框架, 既可以进行实时计算, 也可以离线计算操作")}else {println("既不是hadoop 也不是 spark....")}*/name match {case "hadoop" => println("hadoop是大数据中离线存储和计算的框架....")case "spark" => println( "spark是大数据中用于计算的框架, 既可以进行实时计算, 也可以离线计算操作")case _ => println("既不是hadoop 也不是 spark....")}//注意:上面功能和Java中的功能一样!//下面的才是Scala中的模式匹配特有的功能//2.匹配类型println("---2.匹配类型---")//这样做的意义在于不用使用isInstanceOf和asInstanceOf方法val arr2 = Array("hello", 1, CaseDemo)val value = arr2(Random.nextInt(arr2.length))println(value)value match {case a:String => println(s"${a} : 是一个 字符串类型的数据")case a:Int => println(s"${a} : 是一个 int类型的数据")case a:CaseDemo.type => println(s"${a} : 是一个 CaseDemo 类型的数据")}// 注意: 在判断的时候, 如果后面的表达式没有使用的前面的变量, 那么变量可以使用 _ 替代value match {case _:String => println("是一个 字符串类型的数据")case _:Int => println("是一个 int类型的数据")case _:CaseDemo.type => println("是一个 CaseDemo 类型的数据")}//3.匹配集合println("---3.匹配集合---")val arr3 = Array(1,2,3)arr3 match {case Array(1, x, y) => println(x + " " + y) //3 5 //自带breakcase Array(0) => println("only 0")case Array(1, _*) => println("1 ...")case _ => println("没有匹配上")}val li = List(0,1)li match {case 0 :: Nil => println("only 0") //List(0)case x :: y :: Nil => println(s"x: $x y: $y") //x: 3 y: -1 //List(x,y)//case 0 :: xx => println("0 "+ xx)case 0 :: tail => println("0 "+ tail)case _ => println("没有匹配上")}val tup = (2, 3, 5)tup match {case (1, x, y) => println(s"1, $x , $y") //1, 3 , 7case (_, z, 5) => println(z)case _ => println("没有匹配上")}// 4. 模式匹配_守卫val a = StdIn.readInt() // 键盘输入操作a match {case _ if a >= 0 && a <= 3 => println("[0-3]")case _ if a >= 4 && a <= 8 => println("[4-8]")case _ => println("未匹配")}//5.变量声明中隐藏的模式匹配 (了解)println("---4.变量声明中隐藏的模式匹配---")val (x, y) = (1, 2)println(x) //1println(y) //2val (q, r) = BigInt(10) /% 3println(q) //3println(r) //1val arr4 = Array(1, 7, 2, 9)val Array(first, second, _*) = arr4println(first, second) //(1,7)//6.for循环中隐藏的模式匹配 (了解)println("---5.for循环中隐藏的模式匹配---")val map = Map("k1" -> "v1", "k2" -> "v2", "k3" -> "v3")//val map = Map(("k1","v1"),("k2","v2"),("k3","v3"))for ((k, v) <- map) {println(k + ":" + v)}//6.函数式操作中的模式匹配println("---6.函数式操作中的模式匹配---")map.foreach {case (k, v) => println(k, v)}//7.匹配样例类和样例对象println("---7.匹配样例类---")val arr = Array(StartTask("task1"), StopTask)val obj =arr(1)println(obj)obj match {case StartTask(name) => println("start")case StopTask => println("stop")}}
}case class StartTask(name: String) //case class可以带参数,可以封装数据,也可以用作模式匹配
case object StopTask//case object一般都作为模式匹配来使用,不能够带参数
Option类型
作用: 为了避免空指针的错误, 保证调用方法的时候, 返回值不会是Null
定义
scala中,Option类型来表示可选值。这种类型的数据有两种形式:
Some(x):表示实际的值
None:表示没有值
相关的方法:
isEmpty: 判断是否为空, 如果有数据 返回 false 如果没有数据(None) 返回true
get : 用于从Option类型中获取数据, 如果类型为Nont 直接抛出异常, 表达出那个部分出现问题
getOrElse: 当Option类型为None的时候, 返回设置的默认值
示例说明
- 定义一个两个数相除的方法,使用Option类型来封装结果
- 然后使用模式匹配来打印结果
不是除零,打印结果
除零打印异常错误
/*** 定义除法操作* @param a 参数1* @param b 参数2* @return Option包装Double类型*/def dvi(a:Double, b:Double):Option[Double] = {if(b != 0) {Some(a / b)}else {None}}def main(args: Array[String]): Unit = {val result1 = dvi(1.0, 5)result1 match {case Some(x) => println(x)case None => println("除零异常")}}
示例二
示例说明
- 重写上述案例,使用getOrElse方法,当除零时,或者默认值为0
参考代码
def dvi(a:Double, b:Double) = {if(b != 0) {Some(a / b)}else {None}
}def main(args: Array[String]): Unit = {val result = dvi(1, 0).getOrElse(0)println(result)
}
scala中偏函数
偏函数可以提供了简洁的语法,可以简化函数的定义。配合集合的函数式编程,可以让代码更加优雅。
偏函数本质上就是一种函数
格式:
- 偏函数被包在花括号内没有match的一组case语句是一个偏函数
- 偏函数是PartialFunction[A, B]的一个实例- A代表输入参数类型- B代表返回结果类型{case x => 表达式...
}
示例说明
- 定义一个列表,包含1-10的数字
- 请将1-3的数字都转换为[1-3]
- 请将4-8的数字都转换为[4-8]
- 将其他的数字转换为(8-*]
package com.leeimport scala.io.StdInobject Demo01 {/*- 定义一个列表,包含1-10的数字- 请将1-3的数字都转换为[1-3]- 请将4-8的数字都转换为[4-8]- 将其他的数字转换为(8-*]*/def main(args: Array[String]): Unit = {val list1: List[Int] = (1 to 10).toList// 原生写法: 基于普通函数的操作val list2: List[String] = list1.map(i => {if (i <= 3) {"[1-3]"} else if (i >= 4 && i <= 8) {"[4-8]"} else {"(8-*]"}})println(list2)// 偏函数实现:val list3: List[String] = list1.map {case i if i <= 3 => "[1-3]"case i if i >= 4 && i <= 8 => "[4-8]"case _ => "(8-*]"}println(list3)}
}
scala中正则表达式操作
使用scala如何通过正则判断字符串是否符合规则
定义
Regex类
scala中提供了Regex类来定义正则表达式
要构造一个RegEx对象,直接使用String类的r方法即可
建议使用三个双引号来表示正则表达式,不然就得对正则中的反斜杠来进行转义
val regEx = """正则表达式""".r
findAllMatchIn方法
- 使用findAllMatchIn方法可以获取到所有正则匹配到的字符串
示例一
示例说明
定义一个正则表达式,来匹配邮箱是否合法
val r = “”“.+@.+…+”“”.r
合法邮箱测试:qq12344@163.com
不合法邮箱测试:qq12344@.com
package com.leeimport scala.util.matching.Regexobject Demo01 {def main(args: Array[String]): Unit = {//1.定义用于判定邮箱是否正确的正则表达式val regEx: Regex = """.+@.+..+""".r//2. 定义一个邮箱val email = "45781212@qq.com"//3. 判定是否符合规则if (regEx.findAllMatchIn(email).size > 0){// 说明匹配到了数据, 说明传递的字符串是符合规则的println(email+": 符合规则")}else println("不符合规则")}
}
示例二
示例说明
找出以下列表中的所有不合法的邮箱
"38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com"
package com.leeimport scala.util.matching.Regexobject Demo02 {def main(args: Array[String]): Unit = {//1. 定义一个正则表达式: 用于判断邮箱val regEx: Regex = """.+@.+..+""".r//2. 定义一个集合, 内部放置多个邮箱地址val list = List("38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com")//3. 判断过滤操作/*for( i <- list) {if(regEx.findAllMatchIn(i).size <=0 ){println(i)}}*/val list1 = list.filter(i => regEx.findAllMatchIn(i).size <= 0 )println(list1)}
}
scala中异常处理
在scala中如果出现了异常如何处理, 处理的方式有两种: 捕获异常 抛出异常
如何捕获异常 进行处理
格式:
try {// 代码
}
catch {case ex:异常类型1 => // 代码case ex:异常类型2 => // 代码
}
finally {// 代码
}说明:
- try中的代码是我们编写的业务处理代码
- 在catch中表示当出现某个异常时,需要执行的代码
- 在finally中,是不管是否出现异常都会执行的代码
示例
示例说明
- 使用try…catch来捕获除零异常
package com.leeobject Demo01 {/*示例示例说明- 使用try..catch来捕获除零异常*/def main(args: Array[String]): Unit = {try {val a = 1 / 0} catch {case e:Exception => println("出现了异常操作......")}finally {println("模拟除零异常")}}}
- 如何抛出异常
package com.leeobject Demo02 {def main(args: Array[String]): Unit = {throw new Exception("这是一个异常")}
}
基本抛出的语法是与java是一致的, 但是不同在于scala中不需要在方法上 显现将异常抛出, scala认为这种显示操作是一种设计败笔, scala默认不执行try 直接飘出处理
柯里化
柯里化, 主要的目的是为了进行参数分类, 有时候需要传递参数的时候, 可能要传递多个, 多个参数分为两类, 为了能够方便区分, 可以通过柯里化, 将方法拆分成一个参数多个参数列表形式
而且通过柯里化, 可以提供代码的维护性和便利性
在实际使用中, 一般来说, 第一个 括号传递普通参数, 第二个括号传递制定一些规则
相关操作:
package com.leeobject Demo01 {/*- 编写一个方法,用来完成两个Int类型数字的计算 (+ - * / %)- 具体如何计算封装到函数中- 使用柯里化来实现上述操作*/def main(args: Array[String]): Unit = {println(sumNum(10,20))val value1 = calculateNum(10,20)( (a,b) => a + b )val value2 = calculateNum(10,20)( (a,b) => a - b )val value3 = calculateNum(10,20)( (a,b) => a * b )val value4 = calculateNum(10,20)( (a,b) => a / b )val value5 = calculateNum(10,20)( (a,b) => a % b )println(value3)}//柯里化:def calculateNum(a:Int,b:Int)(fun1:(Int,Int) => Int ) ={fun1(a,b)}// 原始写法def sumNum(a:Int,b:Int) = {a + b}def minusNum(a:Int,b:Int) = {a - b}def multiplyNum(a:Int,b:Int) = {a * b}def divideNum(a:Int,b:Int) = {a / b}}
闭包
闭包其实就是一个函数,只不过这个函数的返回值依赖于声明在函数外部的变量。
可以简单认为,就是可以访问不在当前作用域范围的一个函数。
示例一
定义一个闭包
val y=10val add=(x:Int)=>{x+y
}println(add(5)) // 结果15
add函数就是一个闭包
示例二
柯里化就是一个闭包
def add(x:Int)(y:Int) = {x + y}
上述代码相当于
def add(x:Int) = {(y:Int) => x + y}
说明:
闭包指的在执行函数的内容的时候, 函数中使用的变量并不是自己 {} 作用范围内的变量值, 而是使用比这个作用范围更大的 {}内的变量, 我们将这种行为, 称为闭包
闭包存在弊端:
由于闭包 (函数) 会使用比起自己更大范围内数据, 就会导致这个更大范围内的数据的变量数据都被这个函数所加载到, 如果更大的作用范围下数据量非常的庞大, 也会导致这些变量被这个函数进行加载到内存, 从而导致内存使用增大, 然后执行变慢, 甚至出现内存溢出错误
隐式转换和隐式参数
所谓隐式转换,是指以implicit关键字声明的带有单个参数的方法。它是自动被调用的,自动将某种类型转换为另外一种类型。
使用步骤
- 在object中定义隐式转换方法(使用implicit)
- 在需要用到隐式转换的地方,引入隐式转换(使用import)
- 自动调用隐式转化后的方法
示例
示例说明
使用隐式转换,让File具备有read功能——实现将文本中的内容以字符串形式读取出来
步骤
- 创建RichFile类,提供一个read方法,用于将文件内容读取为字符串
- 定义一个隐式转换方法,将File隐式转换为RichFile对象
- 创建一个File,导入隐式转换,调用File的read方法
package com.leeimport java.io.File
import java.text.SimpleDateFormatobject Demo01 {class RichFile(file:File) {def read() = {println("执行了read方法, 读取数据....")}}class RichFile2(format:SimpleDateFormat) {def read() = {println("执行了read方法, 读取数据....")}def eat() = {println(" xxxxx")}def parse() = {println(" 执行parse")}}object Rich_File {implicit def file2RichFile(file:File) = new RichFile(file)implicit def formatRichFile(format:SimpleDateFormat) = new RichFile2(format)implicit val pre_post: (String, String) = "<<<" -> ">>>"}// 方法可以带有一个标记为implicit的参数列表。这种情况,编译器会查找缺省值,提供给该方法。def book(name:String) ( implicit pre_post: (String, String)) ={println( pre_post._1 + name + pre_post._2)}def main(args: Array[String]): Unit = {import Rich_File._/*val file = new File("D:\\传智工作\\上课\\scala")file.read()val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")format.eat()format.parse()*/book("斗破苍穹")}}
什么时候会执行转换:
- 当对象调用类中不存在的方法或者成员时,编译器会自动将对象进行隐式转换
- 当方法中的参数的类型与目标类型不一致时
Scala系列-4、scala中特质、柯里化、闭包等相关推荐
- JS中的柯里化(currying) 转载自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
JS中的柯里化(currying) by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpr ...
- Scala中的柯里化
首先要区分Scala函数与方法的区别,这在Scala中是两个不同概念,只有理解了这两个概念才能理解柯里化. 方法 scala> def add(x:Int, y: Int) = x + y ad ...
- 【译】理解JavaScript中的柯里化
译文开始 函数式编程是一种编程风格,这种编程风格就是试图将传递函数作为参数(即将作为回调函数)和返回一个函数,但没有函数副作用(函数副作用即会改变程序的状态). 有很多语言采用这种编程风格,其中包括J ...
- JavaScript 中函数 柯里化风格的运用
导语 当我第一次看见 柯里化 这个词语的时候,我也表现出一脸懵,在代码程序中,看见这种 "高大上"的一些词汇叫法的时候,下意识的会觉得这个概念很难很深奥,但是当冷静下来,去深究过后 ...
- 7.scala初识 柯里化、隐式参数、隐式转换、视图边界、上界、下界、协变、逆变
1.前言: 学过java我们都知道,java中的继承是对类的增强,java中的代理.装饰是对对象方法的增强.而在scala中,隐式转换和隐式参数是Scala中两个非常强大的功能,隐式的对类的方法进行增 ...
- javascript --- 函数的柯里化 Vue 2.x中柯里化的使用
函数式编程部分重点 参考资料: 函数式编程 柯里化 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数 var add = function (x) {return function(y ...
- 【转载】JS中bind方法与函数柯里化
原生bind方法 不同于jQuery中的bind方法只是简单的绑定事件函数,原生js中bind()方法略复杂,该方法上在ES5中被引入,大概就是IE9+等现代浏览器都支持了(有关ES5各项特性的支持情 ...
- java8柯里化_借助Java 8实现柯里化
在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术.这 ...
- 深入理解函数式编程之柯里化
目录 柯里化定义 柯里化原因 柯里化前奏--需要固定数量参数 实现柯里化--期待固定数量参数 应用柯里化 流程剖析 柯里化定义 在数学和计算机科学中,柯里化是一种将使用多个参数的一个函数转化成一系列使 ...
最新文章
- jenkins获取远程服务器文件,Jenkins用SSH传输文件到远程服务器
- 计算机、数学、运筹学等领域的32个重要算法
- BZOJ 3160 FFT+Manacher
- 【算法知识】详解基数排序算法
- ActiveMQ持久化到mysql
- static_cast
- js 数组 改变长度_Java数组,什么是Java数组?Java数组学习
- [设计模式-结构型]外观模式(Facade)
- knewone最新分享购物网站模板
- 如何加入微服务 Apache ServiceComb 社区
- Python format()函数
- Python数据解析
- java中级程序员需要掌握的一些必备知识
- 如何做好Windows2003服务器安全策略
- 强制显示U盘隐藏文件
- 程序员找工作遇到的“了解、熟悉、精通”的三种技能要求实际上是这样的标准!
- Power BI可视化案例分享
- 网页dom元素过多为什么会导致页面卡顿
- surface pro可以编程c语言吗,surface pro 3就是surface3吗?surface pro 4就是surface4吗
- R语言回归分析-异常观测值
热门文章
- 获取今年的所有法定节假日
- 运维工程师项目案例_724 运维日 | 关爱运维工程师,从不加班开始
- 大厂面试常考的前端算法面试题,建议尽早学会
- AI+Science系列(二):国内首个基于AI框架的CFD工具组件!赛桨v1.0 Beta API介绍以及典型案例分享!
- 龙芯服务器支持安卓吗,国产软硬件打通!龙芯3B4000适配UOS系统、浪潮云海OS云平台...
- 企业在微博遇到负面信息怎么办?
- wxwidgets mysql_关于wxWidgets控件出现乱码
- 不同VLAN间是如何通信的?
- 每一个JavaScript开发者都应该知道的10道面试题
- Spring 3.2.5 集成 Activiti Modeler 5.17.0