我有一个简单的api方法:
def addWishToBoard(wish: Wish, boardId: BoardId, userId: UserId): Option[Board]
如果boardId
和userId
匹配,则会增加希望。
电路板只存储在一个列表中:
private var boards = List.empty[Board]
我在这里使用var来模拟副作用。
实施代码:
def addWishToBoard(wish: Wish, boardId: BoardId, userId: UserId): Option[Board] = {
val board = find(boardId)
.filter(_.ownerId == userId)
.map(board => board.copy(wishes = wish :: board.wishes.toList))
board.foreach(b => boards = b :: boards)
board
}
有没有使用val for board实现这种副作用的功能方法?如何组合返回Unit
的副作用和返回Option[Board]
的纯函数?
答案 0 :(得分:1)
如果我们设法制作电路板,您可以接受将被调用的功能。
def addWishToBoard(wish: Wish, boardId: BoardId, userId: UserId)(sideEffect: Board => Board = identity): Option[Board] =
find(boardId)
.filter(_.ownerId == userId)
.map(board => sideEffect(board.copy(wishes = wish :: board.wishes.toList)))
你也可以使用选项fold
def addWishToBoard(wish: Wish, boardId: BoardId, userId: UserId): Option[Board] =
find(boardId)
.filter(_.ownerId == userId)
.map(board =>board.copy(wishes = wish :: board.wishes.toList))
.fold(None){v =>
sideEffect(v)
Some(v)
}
答案 1 :(得分:0)
目前尚不清楚你想在这里实现什么......
有很多方法可以在不使用val
的情况下编写它。例如:
boards
.find(boardId)
.filter(_.ownerId == userId)
.map(board => board.copy(wishes = wish :: board.wishes.toList))
.map(b => boards = b :: boards; b)
或者,或许,
def addBoard(b: Board) = {
boards = b :: boards
b
}
boards
.find(boardId)
.filter(_.ownerId == userId)
.map(board => board.copy(wishes = wish :: board.wishes.toList))
.map(addBoard)
(顺便说一句,你继续使用这个功能将#34;版本和#34;添加到列表中,而不删除以前的副本 - 这似乎没有多大意义)。
答案 2 :(得分:-2)
scala> case class Board()
defined class Board
scala> val ob = Option.empty[Board]
ob: Option[Board] = None
然后定义以下
scala> implicit class AnyOps[A](val any: A) extends AnyVal {
| def tap(effect: A => Unit): A = { effect(any); any }
| }
defined class AnyOps
然后使用它
scala> ob.tap(println)
None
res9: Option[Board] = None
从功能编程的角度来看,副作用应该通过IO
完成;类似的东西:
scala> import scalaz._; import Scalaz._; import effect._
import scalaz._
import Scalaz._
import effect._
scala> OptionT(ob.point[IO]) >>! { b =>
| IO.putStrLn(b.toString).liftM[OptionT]
| }
res12: scalaz.OptionT[scalaz.effect.IO,Board] =
OptionT(scalaz.effect.IO$$anon$7@3fd8d23d)
这里的返回类型(当然)封装了效果。但是,我强烈怀疑你的程序需要大量重写才能正常运行(即在任何地方都没有var
),所以tap
解决方案可能就是你要找的东西