加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

设计模式 – 双折叠的功能模式

发布时间:2020-12-16 19:22:04 所属栏目:安全 来源:网络整理
导读:让玩具级的柜台如: class Counter private( val next: Int,val str2int: Map[String,Int] ) { def apply( str: String ): (Int,Counter) = str2int get str match { case Some(i) = ( i,this ) case None = ( next,new Counter( next+1,str2int + (str - ne
让玩具级的柜台如:

class Counter private( val next: Int,val str2int: Map[String,Int] ) {
  def apply( str: String ): (Int,Counter)  = str2int get str match {
    case Some(i) => ( i,this )
    case None => ( next,new Counter( next+1,str2int + (str -> next) ) )
  }
}
object Counter {
  def apply() = new Counter( 0,Map() )
}

此类提供String和自然数之间的映射,每次查询新String时,映射都会延迟扩展.

然后我可以编写一个方法,它可以在Iq的Seq中转换字符串的Seq,在遍历期间更新映射.我得到的第一个实现是foldLeft:

def toInt( strs: Seq[String],counter: Counter ): ( Seq[Int],Counter ) =
  strs.foldLeft( (Seq[Int](),counter) ) { (result,str) =>
    val (i,nextCounter) = result._2( str )
    ( result._1 :+ i,nextCounter )
  }

这按预期工作:

val ss = Seq( "foo","bar","baz","foo","baz" )
val is = toInt( ss,Counter() )._1
            //is == List(0,1,2,2)

但我对于实施并不是很满意.问题是我折叠了两个不同的值.是否有一个函数式编程模式来简化实现?

解决方法

您正在寻找的模式是State monad:

import scalaz._
import Scalaz._

case class Counter(next: Int = 0,str2int: Map[String,Int] = Map()) {
  def apply( str: String ): (Counter,Int) = (str2int get str) fold (
    (this,_),(new Counter(next+1,str2int + (str -> next)),next)
  )}

type CounterState[A] = State[Counter,A]

def count(s: String): CounterState[Int] = state(_(s))

def toInt(strs: Seq[String]): CounterState[Seq[Int]] =
  strs.traverse[CounterState,Int](count)

类型注释是不幸的,也许它可以以某种方式消除.无论如何,这是一个它的运行:

scala> val ss = Seq( "foo","baz" )
ss: Seq[java.lang.String] = List(foo,bar,baz,foo,baz)

scala> val is = toInt(ss) ! Counter()
is: Seq[Int] = List(0,2)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读