Scala的收益率是多少?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (8)
  • 关注 (0)
  • 查看 (112)

理解Ruby和Python的收益率。Scala的收益率是什么?

提问于
用户回答回答于

它被用于序列的理解(比如Python的list-理解和生成器,在这里您也可以使用yield)。

它与for结合使用,并将一个新元素写入到结果序列中。

简单的例子:

/** Turn command line arguments to uppercase */
object Main {
  def main(args: Array[String]) {
    val res = for (a <- args) yield a.toUpperCase
    println("Arguments: " + res.toString)
  }
}

F#中的相应表达式是

[ for a in args -> a.toUpperCase ]

from a in args select a.toUpperCase 

Ruby的收益率有不同的影响。

用户回答回答于

产量比map()更灵活,参见下面的示例

val aList = List( 1,2,3,4,5 )

val res3 = for ( al <- aList if al > 3 ) yield al + 1 
val res4 = aList.map( _+ 1 > 3 ) 

println( res3 )
println( res4 )

产量将打印如下:列表(5,6),这是好的

而map()将返回类似于:list(false、false、true、true、true)的结果,但这可能不是您想要的结果。

用户回答回答于
val aList = List( 1,2,3,4,5 )

val res3 = for ( al <- aList if al > 3 ) yield al + 1
val res4 = aList.filter(_ > 3).map(_ + 1)

println( res3 )
println( res4 )

这两段代码是等价的。

val res3 = for (al <- aList) yield al + 1 > 3
val res4 = aList.map( _+ 1 > 3 )

println( res3 ) 
println( res4 )
用户回答回答于
val A = for (i <- Int.MinValue to Int.MaxValue; if i > 3) yield i

“对于每个整数i,如果它大于3,则生成i并将其添加到列表a中。”

可以理解为

对于每个整数

如果它大于

则将其添加到列表

用户回答回答于

它只是作为开始的表达式的一部分出现,该表达式说明如何从现有列表生成新列表。

类似于:

var doubled = for (n <- original) yield n * 2

因此,每个输入都有一个输出项,这与在其他语言中使用PREPT启用的“命令式延续”完全不同,在其他语言中,它提供了一种从几乎任何结构的命令式代码中生成任意长度的列表的方法。

用户回答回答于

关键词yield在Scala中,简单的语法可以很容易调用map

用户回答回答于

这和LINQ差不多select与Ruby和Python的yield基本上,在C#中你会写什么

from ... select ??? 

而在Scala中

for ... yield ???

同样重要的是要明白for-理解不仅适用于序列,而且适用于定义某些方法的任何类型,就像LINQ:

  • 如果您的类型定义了map,它允许for-由单个生成器组成的表达式。
  • 如果它定义flatMap以及map,它允许for-由几个发电机组成的表达式。
  • 如果它定义foreach,它允许for-没有产量的回路(包括单发电机和多台发电机)。
  • 如果它定义filter,它允许for-从iffor表情。
用户回答回答于

首先,Scala的“for理解”相当于Haskell的“do”符号,它只不过是多个一元操作组合的语法。

Scala的“for综合体”是一种语法糖,用于组合多个操作,包括map、flatMap和filter。或foreach。Scala实际上将一个for表达式转换为对这些方法的调用,因此任何提供它们的类,或者它们的子集,都可以用来进行理解。

首先,我们来谈谈翻译。有非常简单的规则:

1)

for(x <- c1; y <- c2; z <-c3) {...}

翻译成

c1.foreach(x => c2.foreach(y => c3.foreach(z => {...})))

2)

for(x <- c1; y <- c2; z <- c3) yield {...}

翻译成

c1.flatMap(x => c2.flatMap(y => c3.map(z => {...})))

3)

for(x <- c; if cond) yield {...}

在scala 2.7上翻译成

c.filter(x => cond).map(x => {...})

或者,在Scala 2.8上

c.withFilter(x => cond).map(x => {...})

与前一个if方法的回退withFilter不可用,但filter有关此问题的更多信息,请参见下面的编辑。

4)这个

for(x <- c; y = ...) yield {...}

翻译成

c.map(x => (x, ...)).map((x,y) => {...})

当你看非常简单的理解,地图/预见的选择看起来,确实,更好。但是,一旦开始编写它们,您就很容易陷入括号和嵌套级别中。当这种情况发生时,理解通常要清晰得多。

我将展示一个简单的例子,并有意省略任何解释。您可以决定哪种语法更容易理解。

l.flatMap(sl => sl.filter(el => el > 0).map(el => el.toString.length))

for{
  sl <- l
  el <- sl
  if el > 0
} yield el.toString.length

编辑

Scala 2.8引入了一种名为withFilter,其主要区别在于,它不是返回一个新的、过滤的集合,而是按需过滤。大filter方法的行为是根据集合的严格性来定义的。为了更好地理解这一点,让我们看一下Scala 2.7List(严格)和Stream(非严格):

scala> var found = false
found: Boolean = false

scala> List.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3
7
9

scala> found = false
found: Boolean = false

scala> Stream.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3

之所以会出现这种差异,是因为过滤器立即应用于List,返回一张赔率列表--因为foundfalse.只有那时foreach已执行,但此时更改了found毫无意义filter已经被处决了。

如属Stream,该条件不能立即应用。相反,每个元素都是由foreach,,,filter测试条件,这使foreach通过found为了说明这一点,这里有一个等价的理解代码:

for (x <- List.range(1, 10); if x % 2 == 1 && !found) 
  if (x == 5) found = true else println(x)

for (x <- Stream.range(1, 10); if x % 2 == 1 && !found) 
  if (x == 5) found = true else println(x)

这导致了许多问题,因为人们期望if按需考虑,而不是事先应用于整个收藏。

Scala 2.8withFilter,也就是不严格,无论收藏的严肃性。下面的示例显示List在Scala 2.8上使用这两种方法:

scala> var found = false
found: Boolean = false

scala> List.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3
7
9

scala> found = false
found: Boolean = false

scala> List.range(1,10).withFilter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3

这会产生大多数人期望的结果,而不会改变filter行为举止。作为旁注,RangeScala 2.7和Scala 2.8之间的关系从非严格改为严格.

扫码关注云+社区

领取腾讯云代金券