Skip to content

Instantly share code, notes, and snippets.

@markus1189
Last active April 5, 2021 08:43
Show Gist options
  • Save markus1189/b356afed7b16e46a5ecfb1a3060d3296 to your computer and use it in GitHub Desktop.
Save markus1189/b356afed7b16e46a5ecfb1a3060d3296 to your computer and use it in GitHub Desktop.
Using given for a function argument in Scala 3
// Example from https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html
import scala.collection.mutable.ListBuffer
import scala.util.chaining.*
class Transaction:
private val log = ListBuffer[String]()
private var aborted = false
private var committed = false
def println(s: String): Unit =
log += s
def abort(): Unit =
aborted = true
def isAborted =
aborted
def commit(): Unit =
if !aborted && !committed then
Console.println("******* log ********")
log.foreach(Console.println)
committed = true
object Transaction:
type Transactional[T] = Transaction ?=> T
def thisTransaction: Transactional[Transaction] =
summon[Transaction]
// literal translation from blog post
def transaction1[T](op: Transactional[T]) =
given trans: Transaction = Transaction()
op
trans.commit()
// using Scala 2's implicit
def transaction2[T](op: Transactional[T]) =
Transaction().tap(implicit _ => op).commit()
// using pattern match in Scala 3
def transaction3[T](op: Transactional[T]) =
Transaction().tap { case _ @ given Transaction => op }.commit()
// using ?=>
def transaction4[T](op: Transactional[T]) =
Transaction().tap(x => op(using x)).commit()
// using explicit application, would like to avoid
def transaction5[T](op: Transactional[T]) =
Transaction().tap(x => op(using x)).commit()
Transaction().tap(op(using _)).commit() // would also work with underscore
extension [A](self: A)
def contextTap[U](f: A ?=> U): A =
f(using self)
self
// using custom tap extension
def transaction6[T](op: Transactional[T]) =
Transaction().contextTap(op).commit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment