scala 组合 继承_Scala:具有类似透镜结构的谓词组合

scala 组合 继承

我一直在思考如何在任意Scala集合上应用类似镜头的构造的一些想法,该构造还结合了谓词组合的功能,而不是功能组合的更标准的概念。 要问一个愚蠢的问题,我们能做些类似于带有“ get”,“ set”和“ mod”但应用于集合的Scalaz镜头的事情吗? 如果我们使用此数据结构采取的行动是基于某些谓词条件的,该怎么办? 如果我们希望通过仅更新列表的部分而不编写完全针对Fizz Buzz的功能来解决Fizz Buzz,该怎么办。 就像是…

val fizz = Choose({x: Int => x % 3 == 0})
val buzz = Choose({x: Int => x % 5 == 0})
val fizzbuzz = fizz and buzz
val myList = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

val result = fizz set("Fizz", buzz set("Buzz", fizzbuzz set("FizzBuzz", myList)))

诚然,列表的输出类型将不同于列表的输入类型,但在理想情况下,它是魔术。

这不是一个新想法。 实际上,之前已经做过非常类似的事情。 哪里? Haskell当然! 看看Haskage:lens 。 在其中,您会看到许多“奇数”结构,其中特别突出的是Traversal 。 我必须承认,遍历非常漂亮,功能强大,而且绝对可以确定。 我将对它进行混蛋,但就像任何拿着枪的新手一样,它的目标是随时射击。

做出选择

在我的谓词库中,我使用以下运算符列出了22个谓词特征:

  • 要么
  • 异或
  • 南德
  • 也不
  • 异或

并为每个定义一个Not运算符。 它与TraversableLike的filter方法一起使用时效果很好(如果我曾经发布过,它仍然可以使用。)但是,我认为我在我编写的整个代码中一半写了以下十五种不同的版本,每个版本都有自己的“ doStuff”方法上:

case class MyClass(pred: SomeType){
  def apply(myCollection: SomeCollectionType) =  myCollection map{ 
    if(pred(x)) doStuff(x) else x 
  }
  def and(that: MyClass) = copy(x => pred(x) && that.pred(x))
}

显然,我想要的东西也具有这些运算符,但它本身不是谓词。 将动作与过滤结合起来的东西是这样的:

class PredicatedMod[A](pred: A => Boolean, f: A => A){
  def apply[Repr <: TraversableLike[A, Repr]](that: Repr) = that map{
    if(pred(x)) f(x) else x
  }
  def and(that: ChooseFunction[A]) = new ChooseFunction(pred and that.pred, f)
  def or(that: ChooseFunction[A]) = new ChooseFunction(pred or that.pred, f)
  //def xor, def nand, etc.

简单的概念,确实可以用几行代码来表达。 实际上, 即使没有谓词组成, PartialFunction也可以做很多事情:

myList map{
  case x if pred(x) => f(x)
  case x => x
}

但是,这仅处理类似镜头的构造的“ mod”情况(对于常数函数为“ set”, f(x)= b) 。对于“ set”的情况,其中包含一些包含的概念,则无法处理。我们想应用的函数中的迭代或变异的数量(假设它是参照透明的。)

明智地选择

那么,什么时候函数具有参照透明性,却又包含一些迭代或突变的概念? 当它在突变状态周围形成局部捕获的闭包时 ,如下所示:

class Set[A](myList: List[A]) extends (List[A] => List[A]){
  def apply(that: List[A]) ={
    val iter = myList.toIterator
    that map{ x =>
      if(iter hasNext ()) iter next () else x
    }
  }
}

这是必须重复编写的PITA,这就是Scala集合库在SeqLike上定义了patch方法的原因 。 更重要的是,patch方法比上面的功能所指示的功能要强大一点,因为它还允许调用者指定起始索引和替换长度。 不幸的是,这是一种全有或全无的操作,具有定义的开始和结束,遍及整个细分市场。

要带走的重要内容不是补丁不适合基于谓词条件的应用程序(不是),而是可以一次处理整个集合。 简而言之,我们可以在上一节中尽量避免使用PartialFunction,因为它逐点地逐段工作,其中集合的每个项目彼此独立。 在此,替换取决于替换了多少先前的值。 换句话说,集合中的每个后续动作都取决于该点之前发生的累积动作集。

class PredicatedSet[A](pred: A => Boolean, myList: List[A]) extends (List[A] => List[A]){
  def apply(that: List[A]) ={
    val iter = myList.toIterator
    that map{ x =>
      if((iter hasNext ()) && pred(x)) iter next () else x
    }
  }
}

就像我之前说过的,一次又一次地写是PITA,不是因为它占用了大量代码,而是因为它只使用了很少的代码,因此我们很想不打包。 将此归纳为一种以上的收藏类型或收藏系列是“乐趣”开始发生的地方,并且容易犯小错误。

创造选择

那个“有趣”的部分,我为您做了。 我在谓词库的新程序包中创建了所谓的选择 。 作为在Scala集合库的非并行版本上工作的“便携式过滤器”的一个实施例,它也是对立的。 我还做了两个变体: 选择忽略 。 后者通过采用包含的谓词条件的逆函数来应用到“ get”,“ set”和“ mod”成员函数中。 最后,一个Choice构成,产生另一个Choice,它是基础谓词的并集(和)。

介绍性段落中的示例? 它有效,有点。 如果将List强制转换为List [Any],则此方法有效 。 “ mod”和“ set”功能不允许更改返回类型。 他们不能。 如果从不满足条件条件(如Never1的情况) 怎么办? 没有更改,没有修改,因此纯粹是昂贵的传递。

我仍在与该库一起玩耍,所以我还没有发布它(好吧,关于在Maven或Sonatype上获取任何东西,我有两个左手的指点。)我可能打算添加一个“开关”您可以将其视为“ modOrElse”的函数,如下所示:

val choice = Choose({x: Int => x %2 == 0}) 
val processed = choice switch(myCollection, f, g)

并且可以想象添加“ partition”,“ fold”和“ scan”成员函数。

在“谓词”部分,我仍在研究有关PartialFunctions的更多想法(例如实际上有22个想法),以及使用隐式类FunctionN提升为PartialFunctionN的简单方法。 当我不花时间与亲人在一起或赶上我过去几年错过的阅读时,这是一项正在进行的工作。

不管怎么说,如果您有想法或想在其中看到某些内容,请分叉并做出贡献,因为我自己的步伐很慢。

参考: Scala: JCG合作伙伴 Owein Reese在静态类型博客上的谓词结构式谓词组合

翻译自: https://www.javacodegeeks.com/2014/01/scala-predicate-composition-with-lens-like-structures.html

scala 组合 继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值