Skillsbench python-scala-functional
Guide for translating Python code to functional Scala style. Use when converting Python code involving higher-order functions, decorators, closures, generators, or when aiming for idiomatic functional Scala with pattern matching, Option handling, and monadic operations.
install
source · Clone the upstream repo
git clone https://github.com/benchflow-ai/skillsbench
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/benchflow-ai/skillsbench "$T" && mkdir -p ~/.claude/skills && cp -r "$T/tasks/python-scala-translation/environment/skills/python-scala-functional" ~/.claude/skills/benchflow-ai-skillsbench-python-scala-functional && rm -rf "$T"
manifest:
tasks/python-scala-translation/environment/skills/python-scala-functional/SKILL.mdsource content
Python to Scala Functional Programming Translation
Higher-Order Functions
# Python def apply_twice(f, x): return f(f(x)) def make_multiplier(n): return lambda x: x * n double = make_multiplier(2) result = apply_twice(double, 5) # 20
// Scala def applyTwice[A](f: A => A, x: A): A = f(f(x)) def makeMultiplier(n: Int): Int => Int = x => x * n val double = makeMultiplier(2) val result = applyTwice(double, 5) // 20
Decorators → Function Composition
# Python def log_calls(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__}") result = func(*args, **kwargs) print(f"Finished {func.__name__}") return result return wrapper @log_calls def add(a, b): return a + b
// Scala - function composition def logCalls[A, B](f: A => B, name: String): A => B = { a => println(s"Calling $name") val result = f(a) println(s"Finished $name") result } val add = (a: Int, b: Int) => a + b val loggedAdd = logCalls(add.tupled, "add") // Alternative: using by-name parameters def withLogging[A](name: String)(block: => A): A = { println(s"Calling $name") val result = block println(s"Finished $name") result }
Pattern Matching
# Python (3.10+) def describe(value): match value: case 0: return "zero" case int(x) if x > 0: return "positive int" case int(x): return "negative int" case [x, y]: return f"pair: {x}, {y}" case {"name": name, "age": age}: return f"{name} is {age}" case _: return "unknown"
// Scala - pattern matching is more powerful def describe(value: Any): String = value match { case 0 => "zero" case x: Int if x > 0 => "positive int" case _: Int => "negative int" case (x, y) => s"pair: $x, $y" case List(x, y) => s"list of two: $x, $y" case m: Map[_, _] if m.contains("name") => s"${m("name")} is ${m("age")}" case _ => "unknown" } // Case class pattern matching (preferred) sealed trait Result case class Success(value: Int) extends Result case class Error(message: String) extends Result def handle(result: Result): String = result match { case Success(v) if v > 100 => s"Big success: $v" case Success(v) => s"Success: $v" case Error(msg) => s"Failed: $msg" }
Option Handling (None/null Safety)
# Python def find_user(user_id: int) -> Optional[User]: user = db.get(user_id) return user if user else None def get_user_email(user_id: int) -> Optional[str]: user = find_user(user_id) if user is None: return None return user.email # Chained operations def get_user_city(user_id: int) -> Optional[str]: user = find_user(user_id) if user is None: return None address = user.address if address is None: return None return address.city
// Scala - Option monad def findUser(userId: Int): Option[User] = db.get(userId) def getUserEmail(userId: Int): Option[String] = findUser(userId).map(_.email) // Chained operations with flatMap def getUserCity(userId: Int): Option[String] = findUser(userId) .flatMap(_.address) .map(_.city) // For-comprehension (cleaner for multiple operations) def getUserCity(userId: Int): Option[String] = for { user <- findUser(userId) address <- user.address city <- Option(address.city) } yield city // Getting values out val email = getUserEmail(1).getOrElse("no-email@example.com") val emailOrThrow = getUserEmail(1).get // Throws if None
Generators → Iterators/LazyList
# Python def fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b # Take first 10 fibs = list(itertools.islice(fibonacci(), 10))
// Scala - LazyList (was Stream in Scala 2.12) def fibonacci: LazyList[BigInt] = { def loop(a: BigInt, b: BigInt): LazyList[BigInt] = a #:: loop(b, a + b) loop(0, 1) } val fibs = fibonacci.take(10).toList // Alternative: Iterator def fibonacciIterator: Iterator[BigInt] = new Iterator[BigInt] { private var (a, b) = (BigInt(0), BigInt(1)) def hasNext: Boolean = true def next(): BigInt = { val result = a val newB = a + b a = b b = newB result } }
Try/Either for Error Handling
# Python - exceptions def parse_int(s: str) -> int: try: return int(s) except ValueError: return 0 # Python - Optional for errors def safe_parse_int(s: str) -> Optional[int]: try: return int(s) except ValueError: return None
// Scala - Try monad import scala.util.{Try, Success, Failure} def parseInt(s: String): Try[Int] = Try(s.toInt) val result = parseInt("123") match { case Success(n) => s"Got: $n" case Failure(e) => s"Error: ${e.getMessage}" } // Chaining Try operations val doubled = parseInt("123").map(_ * 2) // Either for custom error types def parsePositive(s: String): Either[String, Int] = { Try(s.toInt).toEither .left.map(_ => "Not a number") .flatMap { n => if (n > 0) Right(n) else Left("Must be positive") } }
Function Composition
# Python def compose(f, g): return lambda x: f(g(x)) def pipe(*functions): def inner(x): result = x for f in functions: result = f(result) return result return inner # Usage add_one = lambda x: x + 1 double = lambda x: x * 2 pipeline = pipe(add_one, double, add_one) # (x + 1) * 2 + 1
// Scala - built-in composition val addOne: Int => Int = _ + 1 val double: Int => Int = _ * 2 // compose: f.compose(g) = f(g(x)) val composed = addOne.compose(double) // addOne(double(x)) // andThen: f.andThen(g) = g(f(x)) val pipeline = addOne.andThen(double).andThen(addOne) // (x + 1) * 2 + 1
Currying and Partial Application
# Python from functools import partial def add(a, b, c): return a + b + c add_5 = partial(add, 5) result = add_5(3, 2) # 10
// Scala - curried functions def add(a: Int)(b: Int)(c: Int): Int = a + b + c val add5 = add(5) _ // Partially applied val result = add5(3)(2) // 10 // Converting between curried and uncurried val uncurried = Function.uncurried(add _) val curried = (uncurried _).curried // Multiple parameter lists def fold[A, B](init: B)(list: List[A])(f: (B, A) => B): B = list.foldLeft(init)(f) val sum = fold(0)(List(1, 2, 3))(_ + _)
Tail Recursion
# Python - no tail call optimization def factorial(n): if n <= 1: return 1 return n * factorial(n - 1) # Workaround: iterative def factorial_iter(n): result = 1 for i in range(2, n + 1): result *= i return result
// Scala - tail recursion with annotation import scala.annotation.tailrec def factorial(n: Int): BigInt = { @tailrec def loop(n: Int, acc: BigInt): BigInt = { if (n <= 1) acc else loop(n - 1, n * acc) } loop(n, 1) }
Implicit Conversions and Type Classes
# Python - no direct equivalent # Duck typing provides flexibility
// Scala - type classes via implicits (Scala 2) or given/using (Scala 3) // Scala 3 trait Show[A]: def show(a: A): String given Show[Int] with def show(a: Int): String = s"Int: $a" def display[A](a: A)(using s: Show[A]): String = s.show(a) // Scala 2 trait Show[A] { def show(a: A): String } implicit val intShow: Show[Int] = new Show[Int] { def show(a: Int): String = s"Int: $a" } def display[A](a: A)(implicit s: Show[A]): String = s.show(a)