以字符串检查为例了解集合和序列

Understanding Sets and Sequences using String checking as an example

我有一个字符串,我想交叉检查它是否完全由字母组成 space。

 val str = "my long string to test"
 val purealpha = " abcdefghijklmnopqrstuvwxyz".toSet

 if (str.forall(purestring(_))) println("PURE") else "NOTPURE"

上面的简明代码完成了这项工作。但是,如果我 运行 这样:

 val str = "my long string to test"
 val purealpha = " abcdefghijklmnopqrstuvwxyz"   // not converted toSet

 str.forall(purealpha(_))    // CONCISE code

我得到一个错误(找到:Char ... 需要:Boolean)并且它只能以这种方式使用 contains 方法工作:

str.forall(purealpha.contains(_))

我的问题是如何在不将字符串转换为 Set 的情况下使用 CONCISE 形式。关于拥有我自己的 String class 以及正确的方法组合以启用漂亮代码的任何建议;或者可能是一些处理字符串的纯函数。

这只是我正在做的一个有趣的练习,所以我可以理解集合的各种方法(包括 apply 方法)的复杂细节以及如何编写漂亮简洁的代码和 classes。

如果我们查看源代码,我们会发现这两种实现都在做不同的事情,尽管给出的结果相同。 当您将其转换为 Set 并使用 forAll 时,您最终是在调用集合的 apply 方法。以下是在您的代码中显式调用 apply 的方式,也在匿名函数中使用命名参数:

if (str.forall(s => purestring.apply(s))) println("PURE") else "NOTPURE" // first example
str.forall(s => purealpha.apply(s)) // second example

总之先看看申请Set的源码(来自GenSetLike.scala):

/** Tests if some element is contained in this set.
   *
   *  This method is equivalent to `contains`. It allows sets to be interpreted as predicates.
   *  @param elem the element to test for membership.
   *  @return  `true` if `elem` is contained in this set, `false` otherwise.
   */
  def apply(elem: A): Boolean = this contains elem

当你离开 String 文字时,你必须专门调用 .contains (这是从 SeqLike.scala 获得的源代码):

/** Tests whether this $coll contains a given value as an element.
   *  $mayNotTerminateInf
   *
   *  @param elem  the element to test.
   *  @return     `true` if this $coll has an element that is equal (as
   *              determined by `==`) to `elem`, `false` otherwise.
   */
  def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem)

如您所想,申请 String 字面值与申请 Set 的结果不同。

关于更简洁的建议是在第二个示例中完全省略 (_)(编译器类型推断会选择它):

val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz"   // not converted toSet
str.forall(purealpha.contains)

一种略有不同的方法是使用正则表达式模式。

val str = "my long string to test"
val purealpha = "[ a-z]+"
str matches purealpha   // res0: Boolean = true