Skip to main content

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.

Quellinformationen

Repository
benchflow-ai/skillsbench
Letzte Quellaktivität
21. Januar 2026 um 08:46
Erkannte Sprache von SKILL.md
Englisch
Sterne
1.850
Forks
370

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
python-scala-functional
description
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.
# Python to Scala Functional Programming Translation ## Higher-Order Functions ```python # 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 // 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 # 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 // 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 # 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 // 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 # 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 // 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 # 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 // 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 # 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 // 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 # 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 // 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 # 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 // 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 # 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 // 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 # Python - no direct equivalent # Duck typing provides flexibility ``` ```scala // 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) ```
Auf GitHub ansehen