首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是避免在调用堆栈中传递状态选择上下文的“函数方式”?

什么是避免在调用堆栈中传递状态选择上下文的“函数方式”?
EN

Stack Overflow用户
提问于 2012-03-16 10:18:58
回答 4查看 1.6K关注 0票数 11

假设我有一个有两个列表的特征。有时我对其中一个感兴趣,有时对另一个感兴趣。

代码语言:javascript
复制
trait ListHolder {
  val listOne = List("foo", "bar")
  val listTwo = List("bat", "baz")
}

我有一个函数调用链,在其顶部有我需要在列表之间选择的上下文,但在其底部我使用了特征。

在命令式范式中,我通过函数向下传递上下文:

代码语言:javascript
复制
class Imperative extends Object with ListHolder {
  def activeList(choice : Int) : List[String] = {
    choice match {
      case 1 => listOne
      case 2 => listTwo
    }
  }
}

def iTop(is : List[Imperative], choice : Int) = {
  is.map{iMiddle(_, choice)}
}

def iMiddle(i : Imperative, choice : Int) = {
  iBottom(i, choice)
}

def iBottom(i : Imperative, choice : Int) = {
  i.activeList(choice)
}

val ps = List(new Imperative, new Imperative)
println(iTop(ps, 1)) //Prints "foo, bar" "foo,bar"
println(iTop(ps, 2)) //Prints "bat, baz" "bat, baz"

在面向对象的范例中,我可以使用内部状态来避免向下传递上下文:

代码语言:javascript
复制
class ObjectOriented extends Imperative {
  var variable = listOne
}

def oTop(ps : List[ObjectOriented], choice : Int) = {
  ps.map{ p => p.variable = p.activeList(choice) }
  oMiddle(ps)
}

def oMiddle(ps : List[ObjectOriented]) = oBottom(ps)

def oBottom(ps : List[ObjectOriented]) = {
  ps.map(_.variable)  //No explicitly-passed-down choice, but hidden state
}

val oops = List(new ObjectOriented, new ObjectOriented)

println(oTop(oops, 1))
println(oTop(oops, 2))

在函数式语言中实现类似结果的惯用方法是什么?

也就是说,我希望下面的输出与上面的输出类似。

代码语言:javascript
复制
class Functional extends Object with ListHolder{
  //IDIOMATIC FUNCTIONAL CODE
}

def fTop(fs : List[Functional], choice : Int) = {
    //CODE NEEDED HERE TO CHOOSE LIST
    fMiddle(fs)
}

def fMiddle(fs : List[Functional]) = {
   //NO CHANGES ALLOWED
   fBottom(fs)
}

def fBottom(fs : List[Functional]) = {
  fs.map(_.activeList) //or similarly simple
}

def fs = List(new Functional, new Functional)

println(fTop(fs, 1))
println(fTop(fs, 2))

更新:这会被认为是正常的功能吗?

代码语言:javascript
复制
class Functional extends Imperative with ListHolder{}

class FunctionalWithList(val activeList : List[String]) extends Functional{}

def fTop(fs : List[Functional], band : Int) = {
  fMiddle(fs.map(f => new FunctionalWithList(f.activeList(band))))
}

def fMiddle(fs : List[FunctionalWithList]) = {
  //NO CHANGES ALLOWED
  fBottom(fs)
}

def fBottom(fs : List[FunctionalWithList]) = {
  fs.map(_.activeList)
}

def fs = List(new Functional, new Functional)

println(fTop(fs, 1))
println(fTop(fs, 2))
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-03-17 10:56:46

好吧,人们总是可以使用单数和一元理解来处理这类事情,但问题的核心是,不是将选择向下传递到堆栈中,而是在堆栈中向上返回函数,直到有人知道如何解决问题可以处理它。

代码语言:javascript
复制
def fTop(fs : List[Functional]) = {
    fMiddle(fs)
}

def fMiddle(fs : List[Functional]) = {
   fBottom(fs)
}

def fBottom(fs : List[Functional]) = {
 (choice: Int) => fs map (_ activeList choice)
}

然后

代码语言:javascript
复制
println(fTop(fs)(1))

一旦你开始为这类事情开发模式,你就会得到各种各样的monad (每种monad代表一种特定的模式)。

票数 8
EN

Stack Overflow用户

发布于 2012-03-16 14:34:47

你的第一个命令式版本在我看来是最实用的。

通常,Reader monad和State monad转换器用于在调用堆栈中向下传递上下文或状态。

有关状态单元格的示例,请参阅Scalaz state monad examples,并查看此scalaz邮件list thread,以获得类似的问题和答案。

票数 2
EN

Stack Overflow用户

发布于 2012-03-16 16:08:22

Reader monad可能会有所帮助。请参阅Tony Morris's blog

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9730983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档