首先需要Scala开发环境的搭建,网上自己找教程。

声明常量与变量

val foo = 0  // 常量
var bar = 0 // 变量

  

在Scala中,更加鼓励使用val来进行声明,也就是推荐使用常量。在大部分时候不需要分号,看自己便好…虽然是强静态类型的语言,但是却并没有写出类型——这就是类型推断。

也可以指定类型:

val spark: String = "Hello Scala"

  

多个的同时声明:

val xInt, yInt = 100  // xInt, yInt都声明为100

  

常用类型

与Java类似,Scala中也有表示数值类型的类,但是Scala不区分基本类型和引用类型。也就是说Scala中一切都是对象了吧。

Scala对Java中的数值类型的功能添加了许多功能上的强化,这其中涉及了隐式转换。比如,String类型转换成StringOps类型。还有RichInt、RichDouble等对应Int、Double类型。至于有什么新加的方法,可以查看Scala API。

操作符

算数操作符应该与预期中的没有什么差异,因为如果有差异用起来就有麻烦了。但算数操作符事实上是方法。

a + b  相当于  a.+(b)

对于带有一个隐式参数和一个显式参数的方法来说,通常都可以这么简化。如:

1.to(10)  这会产生一个1-10的Range实例,相当于  1 to 10

两种风格任君选择。

Scala没有提供++和–(别认为我打错了,这里是有两个-号的)这两个其他语言中很常见常用的操作符,理由是:不值得为少按一个键而额外增加一个特例。

Scala中可以对操作符进行重载。

调用函数和方法

函数(function)和方法(method)

引入相应的包后,使用函数很简单,不需要从某个类中调用静态方法。

math.sqrt(2)  等同于  scala.math.sqrt(2)  // 以scala.开头的包名,都可以省去该前缀

  

Scala中没有静态方法,但是有单例对象和伴生对象之类的概念可以实现差不多的特性,这些估计到后面会细说。

BigInt.probablePrime(100, util.Random)

  

通常,使用没有参数,且不改变当前对象的方法时,不带圆括号。

apply方法

s是一个字符串,而 s(4) 将会返回该字符串中第4个字符。在使用形如 s(4) 这种,类似于函数调用的语法时,实际上是调用了 apply() 方法。也就是说, s(4) 等于 s.apply(4)

两个容易混淆的概念——表达式(expression)和语句(statement)。表达式有值,而语句没有值只执行操作。

要说起这一点的原因是,Scala中,几乎所有构造出来的语法结构都有值,也就是表达式。这可以使程序更加精简易读。

举例,if表达式是有值的;语句块也是有值的,是最后一个表达式的值。

而对应Java中的void,Scala中有一个类型Unit,用来表示“无有用值”(void表示没有值,这里还是有差别的)。

条件表达式

if/else表达式在Scala中是有值的,除开这一点,与Java等语言没有什么差别。而有值所带来的效果,可以是下面这样子的:

val s = if (x > 0) 1 else -1
// 与上等效的另一种写法
if (x > 0) s = 1 else s = -1

  

第一种写法可以用来初始化一个val,而第二种则要求s必须是var。前面也说了,Scala中更鼓励使用val。

同时,这样的条件表达式,还可以实现比三目操作符 ? : 更加灵活的功能。

如果在if和else两边的类型是不同的,比如:

if (x > 0) "positive" else -1

  

这时返回的类型将会是两个分支类型的公共超类型(这里是String和Int的公共超类型Any)。

如果没有else部分,那么if表达式有可能不返回值,这时候就需要前面提到的Unit类型,写做()。

if (x > 0) 1
// 这相当于else部分返回Unit类型,相当于下面的写法
if (x > 0) 1 else ()

  

语句终止

分号不是必须的,但是使用它们不会带来坏处。

能根据上下文判断出语句结尾的地方,都不需要使用分号。怎么判断是否语句结尾,以后在编码过程中会慢慢积累起感觉的。

如果需要在单行中写多个语句,那么就需要使用分号了。而在写一个较长的语句时,如果需要分行写,要确保前面的行尾需要以不能用来语句结尾的符号来结束。比如说像是下面的操作符:

a = s0 + (v - v0) * t + // +说明了这里不是语句结束哦
0.5 + (a - a0) * t * t
// 下面这种写法就会出问题了
a = s0 + (v - v0) * t
+ 0.5 + (a - a0) * t * t

  

这里还可以发现的是,Scala推荐使用两个空格来缩进。

由于判断语句终止的需要,Scala程序员更倾向于使用Kernighan & Ritchie风格的花括号(也就是Java中推荐的方法):

if (n > 0) {
r = r * n
n -= 1
}

  

块表达式和赋值

Scala中,{ }包含一系列的表达式,而且{ }最后返回的也是一个表达式——最后一个表达式。

而赋值语句的值,是Unit类型的。这也大体上决定了在Java和C++中的 x = y = 1 会出现的赋值语句,几乎不可能出现在Scala中。

输入和输出

输入函数: readLine()、 readInt()等,用来从控制台Console中读取输入。

而输出部分,则是很常见的 print()、 println()、 printf()。

循环

看看Scala中的for循环:

for (i <- expression)  // 让i遍历表达式的所有值,遍历的执行取决于表达式的类型
// 例子
for (i <- 1 to n) // 遍历1到n
for (i <- 0 util s.length) // 遍历0到s.length-1
// 遍历求和
var sum = 0
for (ch <- "Hello") sum += ch

  

事实上,Scala中更多是使用函数式而不是指令式的风格来遍历等操作。后面会见到的。

高级for循环和for推导式

在一个for循环中使用多个“generator”(生成器):

for (i <- 1 to 3; j <- 1 to 3) print ((10 * i +j) + " "
// 结果:11 12 13 21 22 23 31 32 33

  

在for循环中使用“filter ”(过滤器,守卫)来过滤一部分不符合条件的枚举情况:

for (i <- 1 to 3; j <- 1 to 3 if i != j) print ((10 * i + j) + " ")
// 结果:12 13 21 23 31 32

  

可以使用多个filter,中间需要使用分号分隔。

可以在for表达式中使用任意多的定义,引入在循环中使用变量:

for (i <- 1 to 3; from = 4 - i; j <- from to 3) print ((10 * i + j) + " ")
// 结果:13 22 23 31 32 33

  

如果for表达式的循环体是以yield关键词开始的,那么该循环会构造出一个集合,这被称为for推导式。推导式生成的集合与第一个generator是类型兼容的。

for (c <- "Hello"; i <- 0 to 1) yield (c + i).toChar
// 生成"HIeflmlmop"

  

还可以将for表达式的小括号换成花括号,这样可以省去写分号的功夫。

for表达式内容不少,而且这里也不是全部。在《Programming in Scala》中,还有一些高级的讨论,这里就先略了,先入个门。

函数

在Java中并没有函数这个概念,函数的功能是用静态方法来实现的。

函数的定义:

def 函数名(指明类型的参数): 可选的返回值类型 = 函数体
def fac(n: Int) = {
var r = 1
for (i <- 1 to n) r = r * i
r
}

  

只要函数不是递归的,就不需要给出函数的返回值类型(因为有类型推断)。一个递归的函数需要如下写:

def fac(n: Int): Int = if (n <= 0) 1 else n * fac(n - 1)

  

在Scala中,并不时常使用return来返回值。

默认参数和带名参数

Java里似乎没有默认参数和带名参数,至少我从来没有使用过。但记得C++是有的。

def decorate(str: String, left: String = "[", right: String = "]") =
left + str + right

  

上面的函数有两个带有默认值的参数left和right。如果不给出这两个参数,调用这个函数,会使用默认值。也可以给出自己的参数来替代默认的。

参数个数不够时,将会从后往前使用默认参数。

调用函数时,如果指定参数名,那么参数可以不按照参数列表的顺序来:

decorate("Hello", right = "]<<<")

从上面还可以知道,可以混用未命名参数和带名参数。

变长参数

def sum(args: Int*) = {
var result = 0
for( arg <- args) result += arg
result
}

  

星号表示可接受变长参数列表。函数实际得到的参数是Seq类型的。

但是在调用变长参数函数时,并不能直接使用Seq类型的参数。要将一个Seq类型打散成单个的参数序列,使用 : _*。

def recursiveSum(args: Int*) = {
if (args.length == 0) 0
else args.head + recursiveSum(args.tail: _*)
}

  

过程(procedure)

过程的定义与函数很类似。函数体在花括号中,而且花括号前没有=号,返回值是Unit类型的,这就是过程了。(也可以写出=号,并且写明返回值是Unit类型来定义过程。)

通常,过程没有返回值,只是为了副作用而调用一个过程。

懒值

当val被声明为lazy时,初始化会被推迟到首次对其取值时。

lazy val words = io.Source.fromFile("/usr/share/dict/words").mkString

  

如果程序一直不妨问words,那么Scala也不会去打开那个文件。文件是在实际第一次使用words时被打开的。

懒值对开销较大的初始化语句十分有用,可以应对一些初始化问题比如循环依赖。还是开发懒数据结构的基础。

可以将懒值当成是介于val和def的中间状态:

  • val在被定义时即被取值
  • lazy val在首次使用时被取值
  • def在每次使用时取值

异常

Scala中异常机制与Java和C++中一样。但Scala中并没有受检异常,也就是不需要说明函数方法可能会抛出什么异常。

使用throw来抛出一个异常。throw表达式的类型是Nothing。

捕获异常:

try {
process(new URL("http://horstmann.com/fred-tiny.gif"))
} catch {
case _: => MalformedURLException => println("Bad URL: " + url)
case ex: IOException => ex.printStackTrace()
}

  

如果不需要使用捕获的异常对象,使用_来代替变量名(_是Scala中的通配符)。

同时也有try/finally语句,通常用来清理。可以组合成try/catch/finally语句

fRom: http://nerd-is.in/2013-08/scala-learning-control-structures-and-functions/

  

  

 

Scala基础入门-1的更多相关文章

  1. Scala 基础入门【翻译】

    原文地址 本文只是带你进入 Scala 的世界,包括安装.不可变量 val.可变量 var.定义类.集合(包括列表(list).集(set).映射(map))以及集合遍历和集合库(能达到并行/并发效果 ...

  2. Scala基础入门-4

    Scala学习——类 简单类和无参方法 class Counter { private var value = 0 // 必须初始化字段 def increment() { value += 1 } ...

  3. Scala基础入门-3

    学习Scala——映射和元组 映射和和元组,也就是Maps和Tuples.Map这东西应该都挺明白的,就是键值对的集合.而元组,tuple,这东西并不是每个语言都有(Python中是有的,不过当时学的 ...

  4. Scala基础入门-2

    简单类和无参方法 class Counter { private var value = 0 // 必须初始化字段 def increment() { value += 1 } // 方法默认公有 d ...

  5. Scala基础入门-代码碎片

    import scala.util.control._ import java.util.Date object Test { def main(args: Array[String]) { // v ...

  6. scala基础入门

    1.scala当中申明值和变量 scala当中的变量申明可以使用两种方式,第一种使用val来申明变量.第二种使用var来申明变量. 申明变量语法 val/var 变量名 [:变量类型] = 变量值 其 ...

  7. Scala快速入门 - 基础语法篇

    本篇文章首发于头条号Scala快速入门 - 基础语法篇,欢迎关注我的头条号和微信公众号"大数据技术和人工智能"(微信搜索bigdata_ai_tech)获取更多干货,也欢迎关注我的 ...

  8. 【原创 Hadoop&Spark 动手实践 5】Spark 基础入门,集群搭建以及Spark Shell

    Spark 基础入门,集群搭建以及Spark Shell 主要借助Spark基础的PPT,再加上实际的动手操作来加强概念的理解和实践. Spark 安装部署 理论已经了解的差不多了,接下来是实际动手实 ...

  9. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

随机推荐

  1. iOS 获取系统目录

    //获取根目录 NSString *homePath = NSHomeDirectory(); NSLog(@"Home目录:%@",homePath); //获取Document ...

  2. python面向对象(上)

    创建类 Python 类使用 class 关键字来创建.简单的类的声明可以是关键字后紧跟类名: class ClassName(bases): 'class documentation string' ...

  3. CSS 怀疑 Verify

    1. height 之前好像看到有人说,div标签的height设置一个固定值后,div标签的height会随着内容的增多而变大 经测试,内容会溢出div标签,但div标签的height不会随着变化

  4. VSFTP服务

    互联网最开始的三大服务:HTTP.mail.FTP 一.文件服务器简介     FTP:在内网和公网使用.服务器:windows,Linux    客户端:windows,Linux     samb ...

  5. java性能优化技巧

    在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序性能. 1. 尽量使用final修饰符. 带有final修饰符的类是不可派生的. ...

  6. ADO.NET帮助类DBHelper

    一. DBHelper帮助类 using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  7. MYSQL create database 和 create table 做了一些什么!

    create database Studio; 这样就可以创建一个数据库了.他包涵一些什么呢? 可以看到它创建了一个文件夹,下面我们进去看一下它里面有一些什么东西. 还是先建一张表再进去吧,运行一下这 ...

  8. CentOS下安装Nginx并添加nginx_upload_module

    安装前,最好能保证依赖的系统软件已经升级.    yum update CentOS上安装Nginx,如果只是简单安装,不附加其他第三方模块,一句话可以搞定:    yum install nginx ...

  9. Qt之QTemporaryFile(文件名唯一,且可以自动删除)

    简述 QTemporaryFile类是操作临时文件的I/O设备. QTemporaryFile用于安全地创建一个独一无二的临时文件.临时文件通过调用open()来创建,并且名称是唯一的(即:保证不覆盖 ...

  10. Linux进程间通信——信号集函数

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...