[英]Performance around functional programming in scala
我正在使用下面的東西來學習函數式編程和 scala,我來自 python 背景。
case class Point(x: Int, y:Int)
object Operation extends Enumeration {
type Operation = Value
val TurnOn, TurnOff, Toggle = Value
}
object Status extends Enumeration {
type Status = Value
val On, Off = Value
}
val inputs: List[String]
def parseInputs(s: String): (Point, Point, Operation)
想法是我們有一個光矩陣( Point
),每個Point
可以是On
或Off
,如Status
中所述。 我的輸入是一系列命令,要求TurnOn
、 TurnOff
或Toggle
從一個Point
到另一個Point
的所有燈(使用兩個點定義的矩形區域是左下角和右上角)。
我原來的解決方案是這樣的:
type LightStatus = mutable.Map[Point, Status]
val lightStatus = mutable.Map[Point, Status]()
def updateStatus(p1: Point, p2: Point, op: Operation): Unit = {
(p1, p2) match {
case (Point(x1, y1), Point(x2, y2)) =>
for (x <- x1 to x2)
for (y <- y1 to y2) {
val p = Point(x, y)
val currentStatus = lightStatus.getOrElse(p, Off)
(op, currentStatus) match {
case (TurnOn, _) => lightStatus.update(p, On)
case (TurnOff, _) => lightStatus.update(p, Off)
case (Toggle, On) => lightStatus.update(p, Off)
case (Toggle, Off) => lightStatus.update(p, On)
}
}
}
}
for ((p1, p2, op) <- inputs.map(parseInputs)) {
updateStatus(p1, p2, op)
}
現在我將lightStatus
作為 map 來描述整個矩陣的結束狀態。 這可行,但對我來說似乎功能較少,因為我使用的是可變的 Map 而不是不可變的 object,所以我嘗試將其重新考慮為更實用的方式,我最終得到了這個:
inputs.flatMap(s => parseInputs(s) match {
case (Point(x1, y1), Point(x2, y2), op) =>
for (x <- x1 to x2;
y <- y1 to y2)
yield (Point(x, y), op)
}).foldLeft(Map[Point, Status]())((m, item) => {
item match {
case (p, op) =>
val currentStatus = m.getOrElse(p, Off)
(op, currentStatus) match {
case (TurnOn, _) => m.updated(p, On)
case (TurnOff, _) => m.updated(p, Off)
case (Toggle, On) => m.updated(p, Off)
case (Toggle, Off) => m.updated(p, On)
}
}
})
關於這個過程,我有幾個問題:
(m, item) =>???
function 在foldLeft
部分? 像(m, (point, operation)) =>???
給我語法錯誤非常感謝!
從函數式編程的角度來看,您的代碼受到以下事實的影響:...
lightStatus
Map “保持狀態”,因此需要突變。 如果您可以接受每個燈狀態作為Boolean
值,那么這里的設計不需要突變並且即使在非常大的區域內也具有快速狀態更新。
case class Point(x: Int, y:Int)
class LightGrid private (status: Point => Boolean) {
def apply(p: Point): Boolean = status(p)
private def isWithin(p:Point, ll:Point, ur:Point) =
ll.x <= p.x && ll.y <= p.y && p.x <= ur.x && p.y <= ur.y
//each light op returns a new LightGrid
def turnOn(lowerLeft: Point, upperRight: Point): LightGrid =
new LightGrid(point =>
isWithin(point, lowerLeft, upperRight) || status(point))
def turnOff(lowerLeft: Point, upperRight: Point): LightGrid =
new LightGrid(point =>
!isWithin(point, lowerLeft, upperRight) && status(point))
def toggle(lowerLeft: Point, upperRight: Point): LightGrid =
new LightGrid(point =>
isWithin(point, lowerLeft, upperRight) ^ status(point))
}
object LightGrid { //the public constructor
def apply(): LightGrid = new LightGrid(_ => false)
}
用法:
val ON = true
val OFF = false
val lg = LightGrid().turnOn(Point(2,2), Point(11,11)) //easy numbers
.turnOff(Point(8,8), Point(10,10))
.toggle(Point(1,1), Point(9,9))
lg(Point(1,1)) //ON
lg(Point(7,7)) //OFF
lg(Point(8,8)) //ON
lg(Point(9,9)) //ON
lg(Point(10,10)) //OFF
lg(Point(11,11)) //ON
lg(Point(12,12)) //OFF
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.