Skip to content

Instantly share code, notes, and snippets.

@VAlux
Created December 6, 2018 14:42
Show Gist options
  • Save VAlux/fa84511c90d55ddd40d191122b1fde45 to your computer and use it in GitHub Desktop.
Save VAlux/fa84511c90d55ddd40d191122b1fde45 to your computer and use it in GitHub Desktop.
Attempt to write clean stack calculator in scala.
object Test extends App {
val processCommand: String => List[Int] => List[Int] = {
case "add" => {
case a :: b :: tail => a + b :: tail
case _ => Nil
}
case "sub" => {
case a :: b :: tail => a - b :: tail
case _ => Nil
}
case "mul" => {
case a :: b :: tail => a * b :: tail
case _ => Nil
}
case "div" => {
case a :: b :: tail => a / b :: tail
case _ => Nil
}
case "pop" => {
case _ :: tail => tail
case _ => Nil
}
case "dup" => {
case a :: tail => a :: a :: tail
case _ => Nil
}
case _ => Nil => Nil
}
val lexer: String => List[String] = _.split(" ").toList
// Ugly side-effect crap
val printStackEffect: List[Int] => List[Int] = { stack =>
println(stack)
stack
}
// flip arguments of curried bi-function
def flip[A, B, C]: (A => B => C) => B => A => C =
f => x => y => f(y)(x)
// list is before string (flipped) to fit into fmap without explicit arguments assignment
val processCommandAndPrint: List[Int] => String => List[Int] = flip(processCommand) compose printStackEffect
def calc(input: String): Either[String, Int] = {
val initialStack = List(1, 2, 3, 4)
lexer(input)
.foldLeft(initialStack)(Function.uncurried(processCommandAndPrint)) // A => B => C function is uncurried to (A, B) => C
.headOption
.map(result => Right(result))
.getOrElse(Left("Stack is empty"))
}
println(calc("add sub pop dup dup dup"))
println(calc("pop pop pop pop add"))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment