scala和java抽象类_控制的力量:Scala控制结构和抽象

scala和java抽象类

因此,随着Scala 101系列的发展,我认为现在是在Scala中引入控制结构的适当时机。 在某种程度上,使用Scala语言呈现出一种远景,在这种远景中,与许多其他环境相比,给开发人员提供了更大的自由度,但是其中存在很多选择和责任感 。 因此,我有意识地试图将这篇文章限制为涵盖Scala中控制流和迭代的一些主要风格和选项,它们的不同之处并提供用法示例。 我希望这将成为该语言构建块的“白手起脚”,并希望提供使用时的上下文指导和参考点。 我的理想是,加上对类和对象如何不同以及如何在Scala中进行构造的基础知识的了解,这应该提供一个启动板,以便能够编写高效的Scala代码。  

注意 :本篇文章并不声称或什至没有权威性,但尝试涵盖我发现最有用的某些迭代样式和构造。

因此,事不宜迟,在我们开始攀爬时,让链条发出的喀哒声逐渐响起。

如果()

…是Scala中极少数的内置控制结构之一,并使用大多数Java开发人员熟悉的语法。 在Scala中,实现与Java中的实现略有不同,因为所有语句均应返回结果 。 这是功能语言的普遍趋势,它倾向于错误地绑定和返回变量和值,并且(有效地)充当执行和充实的管道,而不是以“副作用”为中心的处理。 这样,Scala将三元运算符模型用作默认值,从而可以基于if()评估的结果来分配值。

例如 if()作为三元表达式

val result = if (1 > 2) true else false
注意 :–如果评估未能返回结果,则由于类型不匹配,原始变量(如果已初始化)将无法执行,或者变量(如果未初始化)将被初始化为AnyVal。
–初始化的值是不可变的,因此无法重新分配

例如,如果是仅声明一个返回值的三元数

var result2 = if(1>2) 1 // assigns result2 = AnyVal

而做..而

…在Scala中被认为是循环,而不是表达式 ,因为它们不必返回“ 有趣的 ”类型(即,它们可以返回Unit类型,这与Java中Scala的void等效)。 许多功能语言倾向于完全放弃while()构造,而是依赖于递归作为控件抽象,但是,鉴于Scala的多范式本质(它被用作通向功能范式的网关语言),这些语言得到了支持。作为内置控制结构。 因此,通常会回拨while循环,以便采用更具功能性的交互方式(例如使用递归 )。 尽管如此,这是一个标准的whiledo .. while语法示例:

例如 while()和do .. while()

var i = 0
while(i < 3) println("Hello " + {i = i + 1; i} )

要么

do { println("Hello " + { i = i + 1; i } ) } while(i < 3)

为(我到/直到)

..使用与Java 5中增强的for循环类似的语法,但有一些显着的增加,即:表达式作用域值使用类型推断; 使用生成器初始化迭代值,并且表达式中也可以内联多个生成器; 过滤器支持包含在表达式中。 一个简单的例子应该使这一点更清楚:  

例如 for()理解中的生成器和过滤器

for(i <- 1 to 4; j <- 1 until 4 if (i * j % 2 == 0)) { println(i * j) }
如上所示,可以使用“ to”或“ until”指定生成器边界,并且可以在每次迭代期间分配值。 类似地,过滤器允许多个语句(以分号分隔)修剪哪些值进入表达式主体。 使用for()进行的迭代称为表达式 (与loop相对),因为它们通常返回一个值,并且可以用于初始化变量。 这里的一个微妙之处是(通过编译器)通过使用表达式的上下文来推断实现和希望从for()构造返回值。 深入研究,我们可以看到实际上有两种for循环样式 ,一种是命令式的,另一种是函数式的。
祈使样式可以“产生”结果(从表达式返回)这一事实是可以识别的,而祈使样式则用于其副作用 (例如上述示例)。 对于更好奇的读者, 这里很好地介绍了for()表达式的复杂性。 这是一篇很棒的文章,描述了Scala中的for()表达式实际上是闭包的,以及为什么这样做会产生令人惊讶的结果。 作为食欲湿润剂,这里有一些细节滴:
  • for表达式中包含的子句实际上是闭包,因此,它们无法在预期的必要意义上“中断”。
  • 急切求值是大多数for()表达式的默认实现。
  • 使用集合的.view可以对break子句进行“实时” (即lazy )评估。 (注意:view替换了[now]不推荐使用的.projection方法)
  • 但是…要实际上早点退出关闭,应根据投影的替代对象评估中断条件。

用于使用函数形式()理解例如 An例如:

var multiplesOfTwo = for(i <- 1 to 10 if i % 2 == 0) yield i

例如 ,通过中断门对()理解进行惰性评估

var gate = true // note this has to be a 'var' type, as we hope to reassign the variable during iteration
for(i <- testList.view.takeWhile(i => gate)) if(i < 5) println(i) else gate = false
注意:由于视图和投影操作在List上(顾名思义,在列表中),我认为无法将这些“ 转义语义 ”应用于生成器创建的一组值。 但是,在这种使用情况下,while()循环将满足以下需求:  

例如,使用while()逃避非Collection迭代

var index = 1
var escapeGate = false
while(index < 10000000 && !escapeGate) {
    if(index > 5) escapeGate = true
    println(index)
    i += 1
}

列表上的有用操作

列表是主要原因之一(如果不是主),在斯卡拉集合类型,并可以同时轻松地创建和操作。 接下来,我们将看一些典型的List操作及其用法。 以下一些有价值的成员描述是从出色的Scaladoc中免费获得的。  

例如创建一个列表

val testList = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

要么

val testList = 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: 9 :: 10 :: Nil
注意 :::操作是正确的关联。 通常,以冒号结尾的操作往往是正确的关联。 :::操作也可以用于将多个列表连接成一个新列表。 连接不同类型的列表会为各个列表创建一个新的“ 最低公分母 ”类型的元素列表  

例如 List元素之间的继承

class Car; class Vovlo extends Car; class VW extends Car;
var lcdList = List(new Volvo()) ::: List(new VW()) // returns a List of Type 'Car'
另请注意:该List支持一些琐碎的操作,例如head(返回列表的第一个元素)和tail(返回列表的第一个元素之后的列表内容)。 在此将不提供有关这些操作的更多详细信息。  

foreach()

使用:将函数应用于列表的每个元素。 此循环构造用于创建的副作用
例:

testList foreach(x => println(x*2))
注意:如果函数采用单个参数,则不必显式列出方法参数。 同样,下划线“ _”通配符可以替换整个参数列表。 (注意,下划线通配符还有其他细微差别,在用作数组替换时,后跟星号,例如'_ *'):

例如, foreach具有推断的参数

testList foreach(println)

testList foreach(println _)

过滤()  

使用:从列表中选择满足给定谓词的所有元素。
例:

val evensList = testList filter (_ % 2 == 0)

注意:返回列表中元素的顺序将从源列表中保留。

划分()

使用:根据提交的谓词将一个列表分为2个列表,并返回包含返回列表的Tuple2。
例:

val tupleWrappedOddAndEvenLists = testList partition (_ % 2 == 0)
// the individual elements of the Tuple can be accessed in the usual way, e.g.:
println(tupleWrappedOddAndEvenLists._1)

注意: Scala中的元组支持和用法不只是充当简单包装器来输入/返回多个变量,因为它们也可以在提取器中使用 ,因此可以在模式匹配中重用。 这两个主题都超出了本文的范围。

对所有人()

使用:返回一个布尔值,该布尔值指示List的所有元素是否都通过给定的谓词
例:

testList forall(a => a.isInstanceOf[Int])

存在()

用途:根据给定谓词测试给定List的任何元素是否为真
例:

testList exists(a => a == 4)

地图()  

使用:将函数应用于列表的所有元素,并返回包含结果的新列表。
例:

val doubledList = testList map (_ * 2)

flatMap()

使用:与地图操作类似,但是会将结果串联到一个列表中。 例如,给定一个列表列表和一个函数作为输入参数,则返回单个(转换的)列表。
例:

val palindromeList = List(testList, testList reverse) flatMap (_.toList)
注意:尝试从树结构中获取(已转换的)叶节点的单个列表(例如文件系统浏览)或将金融/体育市场的合并列表转换为所需的域模型结构时,此功能特别有用。  

折叠[左/右]()

使用:将给定函数应用于List的所有元素以返回汇总值。 实际上,在进行简洁的串联或求和操作时,这是必不可少的。 foldLeft和foldRight之间的差异是函数应用的方向。 这是不可交换操作的注意事项。

例:

(1 foldLeft testList) (_-_) // This takes the seed value for the consolidated return as 1, before applying the muliplication operation on all elements of the palindromeList (effectively adding the results into a running total)

// to see the difference in foldLeft and foldRight for noncommutative operations, let's look at the minus operations applied with a foldLeft and a foldRight (using the shorthand syntax), and observe how the results differ:

(1 /: testList) (_-_) // left fold on the minus operation returns -54
(testList :\ 1) (_-_) // right fold on the minus operation returns -4
注意:折叠操作的快捷方式语法为/ :(对于foldLeft)和:\(对于foldRight)。 “ /:”的命名方式是这样的:实际上,该操作看起来像“发生折叠”的方向,并以分号表示要从哪个方向进行输入。 因此,上面的(1 foldLeft palindromeList)(_ * _)等效于(1 / /:palindromeList)(_ * _)  

相关: 变态

减少[左/右]()

使用:将给定函数递归应用于List中的元素。 第一次迭代的结果值用作后续迭代的主要输入,这是替换模式,然后递归应用。
例:

testList reduceLeft ((a, b) => if (a > b) a else b)
到目前为止,这是Scala中可用的各种控制结构,抽象和List操作中的一部分,应该为执行初始Scala kata提供坚实的基础。 最后值得注意的一点是,Scala编译器会通过将所有尾部递归操作包装在for()循环中来优化尾部递归调用,从而重新使用运行时堆栈帧。 下次,我将尝试介绍Scala语言中最强大的抽象之一,即模式匹配,并展示其与Scala中的Exception处理的相互作用。 希望这一概述为读者提供了适当的知识和深度,以供他们进行进一步的研究,并展示一些递归的力量以及Scala促进编程的功能风格。 祝您黑客愉快!

参考: 具有控制权的力量… Scalabound博客上来自JCG合作伙伴 Kingsley Davies的Scala中的控制结构和抽象


翻译自: https://www.javacodegeeks.com/2012/06/power-with-control-scala-control.html

scala和java抽象类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值