Question regarding contextual abstraction

Hello,

I’ve been trying out new features in Scala 3 for a while, but I’ve got some questions:

  • is it possible to create a contextual function with anonymous function, i.e. val f: Int ?=> Unit = (using x: Int) => ()
  • is it possible to overload a method with different context, i.e. def f(using x: Something) = ??? def f(using x: NotGiven[Something]) = ???

Thank you

Yes. You can choose between these 2:

val f: Int ?=> Unit = (x: Int) ?=> println(x)
val g: Int ?=> Unit = println(summon[Int])

Not really. You can define them, but if you try to call them the compiler won’t choose a method based on the available context or givens. You’ll probably get an ambiguous overload error instead. You could use a different approach.

enum MaybeGiven[+A]:
  case Some(a: A)
  case None
object MaybeGiven:
  given [A](using A): MaybeGiven[A] = Some(summon[A])
  given [A](using NotGiven[A]): MaybeGiven[A] = None

def f(using maybe: MaybeGiven[Something]) =
  maybe match
    case MaybeGiven.Some(x) => ???
    case MaybeGiven.None => ???
1 Like

@Jasper-M Thank you for your help.

The MaybeGiven solution seems to be a useful pattern. Maybe it should be baked into the standard library.

@Jasper-M

On second thought, it seems that the f: MaybeGiven[Something] ?=> T seems can only have one fixed return type.

What I was thinking was actually the builder pattern that was given in the scala 3 document:

def table(init: Table ?=> Unit) =
    given t: Table = Table()
    init
    t

def row(init: Row ?=> Unit)(using t: Table) =
   given r: Row = Row()
   init
   t.add(r)

def cell(str: String)(using r: Row) =
   r.add(new Cell(str))

It’s evident that the outmost function does not use using and returns something while the inner function use using and returns Unit. I was thinking if we can overload them to one function such that we can just do:
table { table { table { } } } for example. This requires that the function being overloaded with different return type. But it seems impossible?