我对Scala有点新意,所以如果这有点微不足道,请道歉.
我有一个我想要迭代的项目列表.我对每个项目执行检查,如果只有其中一个失败,我希望整个函数返回false.因此,您可以将此视为AND条件.我希望它被懒惰地评估,即我遇到第一个错误返回false的那一刻.
我习惯了for - yield过滤通过某个生成器生成的项目的语法(项目列表,序列等).在我的情况下,我只是想突破并返回false而不执行其余的循环.在普通的Java中,人们只会return false;在循环中执行一个操作.
以低效的方式(即当我遇到第一个假项目时不停止),我可以这样做:
(for {
item <- items
if !satisfiesCondition(item)
} yield item).isEmpty
Run Code Online (Sandbox Code Playgroud)
这基本上是说如果没有物品通过过滤器,它们都满足条件.但这似乎有点复杂和低效(考虑到你有100万件物品,第一件已经不满足条件).
在Scala中执行此操作的最佳和最优雅的方法是什么?
在Python中,我可以这样做:
lazy = ((i,j) for i in range(0,10000) for j in range(0,10000))
sum((1 for i in lazy))
Run Code Online (Sandbox Code Playgroud)
这需要一段时间,但内存使用是不变的.
scala中的相同构造:
(for(i<-0 to 10000; j<-i+1 to 10000) yield (i,j)).count((a:(Int,Int)) => true)Run Code Online (Sandbox Code Playgroud)
过了一会儿,我得到了一个java.lang.OutOfMemoryError,尽管应该懒得评价.
如果我使用Option创建一个带有值定义的for comprehension,它将按预期工作:
scala> for (a <- Some(4); b <- Some(5); val p = a * b) yield p
res0: Option[Int] = Some(20)
Run Code Online (Sandbox Code Playgroud)
如果我没有值定义,则使用Either做同样的事情:
scala> for (a <- Right(4).right; b <- Right(5).right) yield a * b
res1: Either[Nothing,Int] = Right(20)
Run Code Online (Sandbox Code Playgroud)
但是如果我使用了值定义,scala似乎推断了for comprehension的错误容器类型:
scala> for (a <- Right(4).right; b <- Right(5).right; val p = a * b) yield p
<console>:8: error: value map is not a member of Product with Serializable with Either[Nothing,(Int, Int)]
for (a <- Right(4).right; b <- Right(5).right; val …Run Code Online (Sandbox Code Playgroud) 最近我接受了Scala Developer职位的采访.我被问到这样的问题
// matrix 100x100 (content unimportant)
val matrix = Seq.tabulate(100, 100) { case (x, y) => x + y }
// A
for {
row <- matrix
elem <- row
} print(elem)
// B
val func = print _
for {
row <- matrix
elem <- row
} func(elem)
Run Code Online (Sandbox Code Playgroud)
问题是:哪种实施方式A或B更有效?
我们都知道,理解可以转化为
// A
matrix.foreach(row => row.foreach(elem => print(elem)))
// B
matrix.foreach(row => row.foreach(func))
Run Code Online (Sandbox Code Playgroud)
B可以写成 matrix.foreach(row => row.foreach(print _))
据说正确答案是B,因为A会创建print100倍以上的函数.
我检查了语言规范,但仍然无法理解答案.有人可以向我解释一下吗?
假设你有很多方法:
def foo() : Try[Seq[String]]
def bar(s:String) : Try[String]
Run Code Online (Sandbox Code Playgroud)
你想做一个for-comprhension:
for {
list <- foo
item <- list
result <- bar(item)
} yield result
Run Code Online (Sandbox Code Playgroud)
当然这不会编译,因为在此上下文中Seq不能与Try一起使用.
任何人都有一个很好的解决方案如何写这个干净而不会分成两个单独的?
我在三分之一的时间里遇到过这种语法问题,并认为现在是时候问这个了.
我正在阅读斯卡拉的不耐烦,我遇到的东西让我摸不着头脑.
以下返回String:
scala> for ( c<-"Hello"; i <- 0 to 1) yield (c+i).toChar
res68: String = HIeflmlmop
Run Code Online (Sandbox Code Playgroud)
但是这会返回一个Vector:
scala> for (i <- 0 to 1; c <- "Hello") yield (c + i).toChar
res72: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p)
Run Code Online (Sandbox Code Playgroud)
这两个例子前面的文字是......
"当for循环的主体以yield开始时,循环构造一个值集合,每次迭代一个......这种类型的循环称为for comprehension.生成的集合与第一个生成器兼容.
如果生成的集合与第一个生成器兼容,那么为什么第二个示例不返回Range类型,如下所示:
scala> val range = 0 to 1
range: scala.collection.immutable.Range.Inclusive = Range(0, 1)
Run Code Online (Sandbox Code Playgroud)
或者我完全误解了文本的意思,"......生成的集合与第一个生成器兼容."
我有一个关于scala中for-comprehension效率的问题.
当perm是大约550个元素的列表时,以下代码大约需要45秒
perm = some list
for{
perm <- perms.withFilter(_.size > 0)
wordList = somefunction(perm) //expensive operation, wordlist is a list of strings
sentenceList = somefunction1(perm) //very expensive operation, sentenceList is a list of list of strings
word <- wordList
sentence <- sentenceList
} yield { word::sentence}
Run Code Online (Sandbox Code Playgroud)
当我将以下代码更改为以下代码时,它使用相同的烫发列表在3秒内运行
perm = some list
for{
perm <- perms.withFilter(_.size > 0)
word <- somefunction(perm) //expensive operation
sentence <- somefunction1(perm) //very expensive operation
} yield { word::sentence}
Run Code Online (Sandbox Code Playgroud)
性能的差异是否与Scala中的延迟评估有关?
我有一段代码,代码如下:
val e2 = for (e <- elements if condition(expensiveFunction(e))) yield {
expensiveFunction(e)
}
Run Code Online (Sandbox Code Playgroud)
条件对于少数元素是正确的,然后对所有剩余的元素变为假.
不幸的是,这不起作用(即使我忽略性能)因为我elements是一个无限的迭代器.
有没有办法在for-comprehension中使用"break",这样当某个条件成立时它会停止产生元素?否则,计算我的scala-idiomatic方法是e2什么?
for {
a <- Some(1)
b <- Some(2)
} yield (a, b)
Run Code Online (Sandbox Code Playgroud)
回报 Some((1, 2))
for {
a <- Right(1).right
b <- Left(2).left
} yield (a, b)
Run Code Online (Sandbox Code Playgroud)
回报 Left((1, 2))
现在我想在理解中分解元组.
for {
(a, b) <- Some((1, 2))
(c, d) <- Some((3, 4))
} yield (a, b, c, d)
Run Code Online (Sandbox Code Playgroud)
回报 Some((1, 2, 3, 4))
for {
(a, b) <- Right((1, 2)).right
(c, d) <- Left((3, 4)).left
} yield (a, b, c, d)
Run Code Online (Sandbox Code Playgroud)
无法编译:
error: constructor cannot be instantiated to expected …Run Code Online (Sandbox Code Playgroud) 如何M在下面的方法中使用for-comprehension类型?
def foo[M[_]: Monad](m1: M[Int], m2: M[Int]) =
for {
a <- m1
b <- m2
} yield (a + b)
Run Code Online (Sandbox Code Playgroud)
我会得到一个
value flatMap is not a member of type parameter M[Int]
Run Code Online (Sandbox Code Playgroud)
我可以通过定义flatMap和map方法来使它工作:
implicit class MOps[A](m: M[A])(implicit monad: Monad[M]) {
def flatMap[B](f: A => M[B]): M[B] = monad.flatMap(m)(f)
def map[B](f: A => B): M[B] = monad.map(m)(f)
}
Run Code Online (Sandbox Code Playgroud)
但是肯定有必要让Cats提供这些方法吗?