小编Ste*_*eve的帖子

为什么必须在scala中的for循环中为模式匹配定义过滤器?

要创建一个可以在Scala中用于理解的新类,似乎所有你需要做的就是定义一个map函数:

scala> class C[T](items: T*) {
     |   def map[U](f: (T) => U) = this.items.map(f)
     | }
defined class C

scala> for (x <- new C(1 -> 2, 3 -> 4)) yield x
res0: Seq[(Int, Int)] = ArrayBuffer((1,2), (3,4))
Run Code Online (Sandbox Code Playgroud)

但这仅适用于简单的for循环,其中左侧没有模式匹配<-.如果您尝试在那里进行模式匹配,则会收到filter未定义方法的投诉:

scala> for ((k, v) <- new C(1 -> 2, 3 -> 4)) yield k -> v
<console>:7: error: value filter is not a member of C[(Int, Int)]
       for ((k, v) <- new C(1 -> 2, 3 -> …
Run Code Online (Sandbox Code Playgroud)

for-loop scala map filter pattern-matching

18
推荐指数
2
解决办法
4721
查看次数

Scala Iterator(又名Iterator.init)中的最后一项除外

我有许多大文件,我想处理除了每个文件中的最后一行以外的所有文件.如果文件很小,我可以转换为TraversableLike并使用"init"方法,例如:

lines.toList.init
Run Code Online (Sandbox Code Playgroud)

但是文件很大所以我需要将事物保存为迭代器.有没有一种简单的方法可以在迭代器上获得类似"init"的内容?我正在考虑以下内容,但我不相信它会一直有效:

lines.takeWhile(_ => lines.hasNext)
Run Code Online (Sandbox Code Playgroud)

iterator scala

17
推荐指数
2
解决办法
7342
查看次数

为什么"mvn编译"需要"test-jar"依赖

test-jar在多模块项目中使用依赖项时遇到问题.例如,当我声明cleartk-syntax模块依赖于cleartk-token模块时test-jar(完整代码在这里):

<modelVersion>4.0.0</modelVersion>
<groupId>org.cleartk</groupId>
<artifactId>cleartk-syntax</artifactId>
<version>0.5.0-SNAPSHOT</version>
<name>cleartk-syntax</name>
...
<dependencies>
    ...
    <dependency>
        <groupId>org.cleartk</groupId>
        <artifactId>cleartk-token</artifactId>
        <version>0.7.0-SNAPSHOT</version>
        <type>test-jar</type>
        <scope>test</scope>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

如果我mvn compile使用maven 2 运行,我会收到以下错误:

[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Failed to resolve artifact.

Missing:
----------
1) org.cleartk:cleartk-token:test-jar:tests:0.7.0-SNAPSHOT
Run Code Online (Sandbox Code Playgroud)

如果我使用maven 3我收到错误:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.654s
[INFO] Finished at: Mon Jan 24 21:19:17 CET 2011
[INFO] Final Memory: 16M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute …
Run Code Online (Sandbox Code Playgroud)

java maven-2 maven-3

15
推荐指数
2
解决办法
1万
查看次数

在Scala中设计一个方便的默认值映射

我发现自己使用了很多嵌套映射,例如Map [Int,Map [String,Set [String]]],我希望在访问新密钥时自动创建新的地图,集等.例如以下内容:

val m = ...
m(1992)("foo") += "bar"
Run Code Online (Sandbox Code Playgroud)

请注意,如果我不需要,我不想在这里使用getOrElseUpdate,因为当你有嵌套的地图并且隐藏代码中实际发生的事情时,它会变得非常冗长:

m.getOrElseUpdate(1992, Map[String, Set[String]]()).getOrElseUpdate("foo", Set[String]()) ++= "bar"
Run Code Online (Sandbox Code Playgroud)

所以我重写了HashMap的"默认"方法.我尝试了两种方法,但都没有完全令人满意.我的第一个解决方案是编写一个创建地图的方法,但是当我声明变量或事情不起作用时,似乎我仍然必须指定完整的嵌套Map类型:

scala> def defaultingMap[K, V](defaultValue: => V): Map[K, V] = new HashMap[K, V] {                      |   override def default(key: K) = {
 |     val result = defaultValue
 |     this(key) = result
 |     result
 |   }
 | }
defaultingMap: [K,V](defaultValue: => V)scala.collection.mutable.Map[K,V]

scala> val m: Map[Int, Map[String, Set[String]]] = defaultingMap(defaultingMap(Set[String]()))
m: scala.collection.mutable.Map[Int,scala.collection.mutable.Map[String,scala.collection.mutable.Set[String]]] = Map()

scala> m(1992)("foo") += "bar"; println(m)                                                    
Map(1992 -> Map(foo -> Set(bar))) …
Run Code Online (Sandbox Code Playgroud)

collections scala type-inference

8
推荐指数
1
解决办法
1105
查看次数

为什么使用foldLeft而不是程序版?

因此,在阅读这个问题时,有人指出,而不是程序代码:

def expand(exp: String, replacements: Traversable[(String, String)]): String = {
  var result = exp
  for ((oldS, newS) <- replacements)
    result = result.replace(oldS, newS)
  result
}
Run Code Online (Sandbox Code Playgroud)

您可以编写以下功能代码:

def expand(exp: String, replacements: Traversable[(String, String)]): String = {
  replacements.foldLeft(exp){
    case (result, (oldS, newS)) => result.replace(oldS, newS)
  }
}
Run Code Online (Sandbox Code Playgroud)

我几乎肯定会写第一个版本,因为熟悉程序或功能样式的编码人员可以轻松阅读和理解它,而只有熟悉功能样式的编码人员才能轻松阅读和理解第二个版本.

但暂时将可读性放在一边,有没有foldLeft比程序版更好的选择呢?我可能认为它会更有效率,但事实证明,foldLeft实现实际上只是上面的过程代码.那么它只是一种风格选择,还是有充分的理由使用一个版本或另一个版本?

编辑:为了清楚,我不是在询问其他功能foldLeft.我与使用非常开心foreach,map,filter等,这些都很好地映射到换内涵.

答:实际上有两个很好的答案在这里(提供delnan戴夫·格里菲斯),即使我只能接受一个:

  • 使用foldLeft是因为还有其他优化,例如使用一个比for循环更快的while循环.
  • 使用fold如果它被添加到常规的集合,因为那样会使平行收藏琐碎的转变.

scala

7
推荐指数
3
解决办法
2374
查看次数

maven使用简单的命令行安装和部署第三方依赖项

我们有许多不在任何地方托管的第三方依赖项.对于其中的每一个,我们都有一个jar文件,我们希望能够安装和/或部署到我们的存储库.一些jar文件有自己的依赖项,我们还需要声明这些.

我们为每个声明groupId,artifactId,依赖项等的jar文件制作了pom.xml文件.这些pom.xml文件都有一个共同的父pom,它声明了一些常见的信息(例如<repositories><distributionManagement>).

我想能够安装或部署这些依赖与作为简单的东西mvn installmvn deploy(或者mvn install:install-filemvn deploy:deploy-file),并拥有所有这些命令的必要的属性(artifactId,repositoryId,等)从pom.xml的文件中读取.

为了使这个工作,至少为了部署,我尝试将以下内容放在我的父pom中:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-deploy-plugin</artifactId>
      <version>2.4</version>
      <configuration>
        <file>${jarfile}</file>
        <pomFile>pom.xml</pomFile>
        <repositoryId>our-id</repositoryId>
        <url>our-url</url>
      </configuration>
    </plugin>
  </plugins>
</build>
Run Code Online (Sandbox Code Playgroud)

然后让每个子poms定义jarfile属性.这允许我运行mvn deploy:deploy-file以部署所有子pom工件.据推测,我可以做类似的事情mvn install:install-file去上班.

但是使用这种方法,我无法释放父pom(我必须这么做,因为孩子poms依赖它),如果我尝试mvn release:perform使用父pom,我会得到如下错误:

Cannot override read-only parameter: pomFile
Run Code Online (Sandbox Code Playgroud)

我觉得我可能会以错误的方式解决这个问题.我真正想做的就是:

  • 将所有第三方jar的公共代码放在一个共享父pom中
  • 为每个第三方jar写一个额外的最小pom
  • 能够运行类似于mvn installmvn deploy不必指定所有那些复杂的命令行属性的东西

我怎样才能做到最好?

编辑:制造这上面清晰的理想,我想能够运行一样简单的东西mvn install或者mvn deploy和没有指定命令行上的属性.

java maven-2 maven-3

6
推荐指数
1
解决办法
1万
查看次数

通过查找sentinel值(在scala中)对可迭代项目进行分组

我有一个来自非常大的文件的行的迭代器,当我移动时需要将它们放入组中.我知道每个组的结束位置,因为每个组的最后一行都有一个标记值.所以基本上我想写一个函数,它接受一个迭代器和一个sentinel值,并返回一个组的迭代器,每个组都由sentinel值终止.就像是:

scala> groups("abc.defg.hi.jklmn.".iterator, '.')
res1: Iterator[Seq[Char]] = non-empty iterator

scala> groups("abc.defg.hi.jklmn.".iterator, '.').toList
res19: List[Seq[Char]] = List(List(a, b, c, .), List(d, e, f, g, .), List(h, i, .), List(j, k, l, m, n, .))
Run Code Online (Sandbox Code Playgroud)

请注意,我希望每个组的末尾都包含标记项.这是我目前的解决方案:

def groups[T](iter: Iterator[T], sentinel: T) = new Iterator[Seq[T]] {                   
  def hasNext = iter.hasNext
  def next = iter.takeWhile(_ != sentinel).toList ++ List(sentinel)
}
Run Code Online (Sandbox Code Playgroud)

我认为这会有效,我想这很好,但每次都要重新添加哨兵给我一个代码味道.有一个更好的方法吗?

grouping iterator scala

5
推荐指数
2
解决办法
867
查看次数

模式匹配args并在轻量级Scala脚本中提供错误消息

我写了一些简单的scala脚本,最后以简单的模式匹配开头,args如:

val Array(path, foo, whatever) = args
// .. rest of the script uses "path", "foo", etc.
Run Code Online (Sandbox Code Playgroud)

当然,如果我提供了错误数量的参数,我会得到一个难以理解的错误:

scala.MatchError: [Ljava.lang.String;@7786df0f
    at Main$$anon$1.<init>(FollowUsers.scala:5)
    ...
Run Code Online (Sandbox Code Playgroud)

是否有一种简单的方法可以提供更有用的错误消息?我目前的解决方法是执行以下操作:

args match {
  case Array(path, foo, whatever) => someFunction(path, foo, whatever)
  case _ => System.err.println("usage: path foo whatever")
}
def someFunction(path: String, foo: String, whatever: String) = {
  // .. rest of the script uses "path", "foo", etc.
}
Run Code Online (Sandbox Code Playgroud)

但是,由于必须定义一个完整的其他功能,并且必须在很多地方重复"路径","foo"和"无论什么",这感觉就像很多样板.有没有更好的办法?我想我可能会丢失函数并将正文放入匹配语句中,但这对我来说似乎不太可读.

我知道我可以使用众多命令行参数解析包中的一个,但我真的在寻找一些非常轻量级的东西,我不需要添加依赖项并修改我的类路径.

error-handling scripting scala pattern-matching

5
推荐指数
1
解决办法
1520
查看次数

实现一个scala集合,以便map,filter等生成正确的类型

我正在尝试实现默认值映射,并且我希望过滤器,映射等等,DefaultingMap以便DefaultingMap尽可能地生成.这是我最初的实现:

class DefaultingMap[K, V](defaultValue: => V)
extends mutable.HashMap[K, V]
with mutable.MapLike[K, V, DefaultingMap[K, V]] {

  override def empty = new DefaultingMap[K, V](defaultValue)

  override def default(key: K): V = {                 
    val result = this.defaultValue
    this(key) = result
    result                                            
  }
}
Run Code Online (Sandbox Code Playgroud)

DefaultingMap使用时会得到类型的对象filter,但是当我使用时却没有map:

scala> val counter = new DefaultingMap[Char, Int](0)
counter: DefaultingMap[Char,Int] = Map()

scala> for (c <- "ababcbbb") counter(c) += 1

scala> counter.filter{case (k, v) => v > 1}
res1: …
Run Code Online (Sandbox Code Playgroud)

scala scala-collections

5
推荐指数
1
解决办法
1708
查看次数