Scala GetStarted


基于IDEA安装运行Scala
因为scala是基于jvm的类python语言。。
使用maven添加scala-library的依赖,即可和java无缝使用。
推荐,以后都使用scala来编写java代码。


Bite-sized introductions to core language features. (核心功能概览)


Scala Style Guide(编程风格)


Scala Language Specification (语言手册)






===============================================================

  • Classes in Scala are blueprints for creating objects


  • Constructors   parameters 也是class的members
    • Primary constructor parameters with val and var are public
  • Constructors parameters without val or var are private values, visible only within the class.
    • 并且默认是val的,不可reassign



  • Members are public by default. 
    • Use the private access modifier to hide them from outside of the class.


  • Notice the special syntax for the setters: the method has _= appended to the identifier of the getter and the parameters come after.
注意,private members,对应的getter and setter的写法
private var _x   = 0    //private members 命名时下划线开头
def x = _x     //getter
def x_= ( newValue : Int ) : Unit = {   //setter 注意写法
    .......
}





Traits are used to share interfaces and fields between classes. 
They are similar to Java 8’s interfaces. 
  • trait可以有abstract field

Classes and objects can extend traits 

but traits cannot be instantiated and therefore have no parameters.







Classes can only have one superclass 
     but many mixins (using the keywords   extends   and   with  respectively)


The mixins and the superclass must have the same supertype


object  XX e xtends App {...}
  • 相当于整个object body,都在main Method body之中。可以直接执行



  • functions are first-class values in Scala


  • salaries.map(x => x * 2)  可以简写为 salaries.map(_ * 2)



函数式编程重要概念:
  • 纯函数~没有副作用
  • 引用透明~相同的输入,总是得到相同的输出
  • 不变性(Immutability)
    • 任何值都是不变的,才能获得引用透明
  • 函数是一等公民(first class)
    • 函数是一种类型。。可以赋给变量
    • 高阶函数(high order):函数作为参数或返回值
    • 闭包:函数引用外部变量。
  • 一切都是表达式,都能计算得值
  • 表达式求值策略:严格求值、非严格求值、惰性求值
  • 递归函数
    • 没有循环。所有循环使用递归实现
    • 递归调优:尾递归
  • currying柯里化


函数式编程优点
  • 简洁(生产效率高)
  • 易于推理(确定输入,有确定输出)
  • 适用于并行编程(多核计算【计算机多个核心】、云计算【即分布式计算】)





  • 作用域保护
    • private[x]protected[x]
    • 这里的x指代某个所属的包、类或单例对象



  • 字面量(literal)
    • 不变量、常量(val)
    • 变量(var)


  • for 循环 多层循环
    • 使用分号 (;) 构成多层循环

  • for 循环过滤
    • Scala 可以使用一个或多个 if 语句来过滤一些元素。

  • for 使用 yield
    • 构成generator??


  • Scala 标识符
    • 普通标识符,与java标识符规则相同
    • 可以使用特殊字符:+, ++, ~, &,-, -- , \, /, : 等
      • 一般要么只使用普通标识符、要么只使用特殊符号
      • 除private变量的setter等特殊情况外
    • 特殊符号 内部实现时会使用转义的标志符,比如:-> 使用 $colon$minus$greater 来表示这个符号
    • java方法名跟scala关键字冲突
      • 例如 Thread.`yield`()



如果你不写等于号和方法主体,
     那么方法会被隐式声明为"抽象(abstract)",包含它的类型于是也是一个抽象类型。



函数参数(function arguments)解析时有两种方式
  • 传名调用(call-by-name)
    • 格式是  varName: (argType...) => returnType
  • 传值调用(call-by-value)
    • 格式是varName : => returnType
  • 区别是:
    • 传名调用,需要声明参数列表
    • 传名调用 传入的是funcName,只有调用【funcName(xxx) 】时,才执行
    • 传值调用,传入的是funcName(xxx)的返回值。


可变参数
Scala 允许你指明函数的最后一个参数是可变参数,
在参数的类型之后放一个星号来设置可变参数



偏函数
使用偏函数优化 存在不变参数的函数,
将不变的参数绑定,使用下划线(_)替换缺失的参数列表,并把这个新的函数的引用的赋给变量(即偏函数)。



function的表示方式:
  • (varName: varType...) => {expressions}
  • 函数返回值是由多个expressions构成的block的值,即最后一个expression的值
  • function是object,所以可以赋值给变量
  • function调用:加括号,传入参数即可调用


函数柯里化(Currying):举例
  • 将函数 【 def add(x:Int,y:Int)=x+y 】柯里化为multiple parameter list的形式 
    • 【def add(x:Int)(y:Int) = x + y】或【def add(y:Int)(x:Int) = x + y】
  • 这样获得的好处是,可以根据参数进行分步调用。。中间每一步返回值都是一个函数。


闭包
  • 引用 函数体外面定义的变量(除function args外)的函数,即闭包
  • 一般引用的外部变量,不允许改变。比如java中,这样的变量必须以final来声明
    • Scala可以使用val来实现类似效果。。但编译器不强制外部变量必须不可变。



在 Scala 中,字符串的类型实际上是 Java String,它本身没有 String 类。
type String = java.lang.String
使用type,来声明type alias



Scala方法调用的简便写法:
  • 【 objectName.methodName(args...) 】可以简化为 【 objectName  methodName (args...) 】
  • 如果args只有一个,可以省略括号
    • 注意tuple的概念和python类似
  • 如果没有args,括号也可以省略
  • 所以AnyVal类型的对象(Int、Double等),都有以+、-、++等运算符号命名的方法。





一个Scala脚本文件与其中的object、class、trait并没有强制的联系
  • 一个文件中可以有任意多个object、class、trait
  • 在$SCALA_HOME/bin目录中,运行scala,进入REPL模式。可以计算expressions
  • scala脚本文件代码可写的位置:
    • 通常在已有package声明的Scala文件中,代码不能写在object、class、trait之外
    • 在object、trait之中,不在Method之中的代码,运行在【static initiation(静态初始化)】阶段
    • 在class之中,不在Method之中的代码,运行在【instance initiation(实例初始化)】阶段,即new对象时。



数组使用【 arrName(expression)】来索引成员



Tuple可以包含不同类型的元素
生成元组:
  • 一般通过圆括号来生成,
  • 但内部是通过new内置的TupleXX(...)来生成。
  • Scala 支持的元组最大长度为 22。对于更大长度你可以使用集合,或者扩展元组
可以使用 t._1 访问第一个元素, t._2 访问第二个元素


List是不可变的,
tail 返回一个列表,包含除了第一元素之外的其他元素


Set分为可变的和不可变。
     默认情况下,Scala 使用的是不可变Set,如果你想使用可变Set,需要引用 scala.collection.mutable.Set 包


不可变集合类,你仍然可以模拟添加,移除或更新操作。
  • 但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变。
  • 不可变集合,都在 scala.collection.immutable包下
    • 可变集合都在scala.collection.mutable包下
  • 一般集合,都有成对的可变集合和不可集合存在。比如
    • List不可变、ListBuffer可变
    • scala.collection.immutable.Set不可变,scala.collection.mutable.Set可变
  • 默认推荐使用不可变集合、不可变的变量(val)
    • 为什么??


mapVar.get(key)返回一个Option[T]对象
Scala Option(选项)类型用来表示一个值是可选的(有值或无值)
  • Option 有两个子类别,一个是 Some,一个是 None,
  • 当他回传 Some 的时候,代表这个成功获取值,而你可以透过 get() 拿到那个 值,
  • 如果他返回的是 None,则代表没有值返回。



重写一个非抽象方法必须使用override修饰符
  • 重写抽象方法时,override关键字可用可不用(推荐加上)


只有一个构造方法
  • Scala不存在方法重载,使用函数默认值取代
extends时,需要加上基类的构造方法:
  • Location(override val xc: Int, override val yc: Int,val zc :Int) extends Point(xc, yc)



  • 伴生对象、伴生类
    • 当object与某个class共享同一个名称时,
    • object称为伴生对象:companion object。class称为伴生类:companion class。
    • 类和它的伴生对象可以互相访问其私有成员


  • 私有构造方法:举例
    • class Marker private(val color:String)


  • 如果定义了apply,就可以使用【ClassName(argVal...)】生成对象
  • 如果定义了unapply,
    • 可以在模式匹配中使用【ClassName(argVal...)  或者ClassName(argVar...) 】
    • 在模式匹配 时,unapply 将自动执行
  • 其中unapply,叫做提取器(Extractor)
    • 提取器是从传递给它的对象中提取出构造该对象的参数。
  • 只有case class和object存在apply、unapply
    • case class的apply、unapply,是自动生成的。
      • 自定义的apply、unapply不会覆盖。是普通方法。
    • object的apply、unapply必须自定义并实现
    • 注意apply~unapply是成对出现的。
      • apply的返回值,是unapply的参数。
      • unapply的返回值Option[Type...],其中Type...对应apply的参数类型




  • 模式匹配机制
    • match-case方式,类似switch-case
    • 可以 类型匹配,用于判断传入的值是否为指定类型


  • 样例类(case classes)
    • 用于模式匹配。
    • 在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象
    • 提供unapply方法使模式匹配可以工作
    • 生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义
    • 类似java bean概念



在Scala里,借用了模式匹配的思想来做异常的匹配,
     因此,在catch的代码里,是一系列case字句,



Scala 进行文件写操作,直接用的都是 java中 的 I/O 类 (java.io.File)
使用 Scala 的 Source 类及伴生对象来读取文件:举例
Source.fromFile("test.txt" ).foreach{
         print
      }


隐式转换


特殊的多变量赋值的写法:
//常见的有Array、Tuple
val Array(hostname , port) = Array("localhost", 8080)
// val ar = (2,3)
// val Tuple2(a, b) = ar



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值