Scala 3 syntax of implicit argument

Hello folks,
How one can rewrite construct like this:

namedDBs.foreach(_() autoCommit { implicit session =>
...
}

in to Scala 3 syntax (I mean avoid to use implicit keyword). The code as is, is compiled by in Scala 3

It depends on the type of the autoCommit. The idiomatic way in Scala 3 would be to define autocommit like this:

def autoCommit(body: Session ?=> Unit): Unit

?=> is a context function type that takes an implicit paremeter of type Session. One you have that your main code becomes simply

namedDBs.foreach: db =>
  db().autoCommit:
    ... // a given of type Session is available here

The idea is that code passed to a parameter of context function type S ?=> T will be expanded to a lambda that will get the S implicitly. No need to write it out.

1 Like

Assuming that you method signature is: def autoCommit[Ctx,R](fn: Ctx => R): R = ??? I don’t think there is currently a clean replacement for that, unless you’d rewrite the method signature itself as Martin suggests. One think that would work is

autoCommit( ctx =>
  given Ctx = ctx
  ???
)

However, if I’d need to keep the original signature for any reasons I’d keep using implicit ctx => ???
It really reminds me one of recent changes to Scala Native to make it more Scala 3 idiomatic: nativelib: Make `Zone.apply` context-function based, add `Zone.acquire` for Scala2 compat by WojciechMazur · Pull Request #3752 · scala-native/scala-native · GitHub

Maybe some functions extensions similar to tupled might be useful allowing to convert A => B into A ?=> B and other way around?

One way is to use pattern bound given instances:

autoCommit{ case given Session => 
  ???
}
3 Likes

Thanks @WojciechMazur and @Odersky for reply.
I can’t change the method signature, it is ScalikeJDBC API.
@WojciechMazur you guess signature very closely :grinning:, and yes I can use your workaround, but it looks strange and is verbose.
@Odersky I understand point but I don’t understand what is the reason, that compiler do not allow just simply substitute implicit with given word in this case (all is pretty clear: scope of application and also source). It look pretty transparent and not damaging. Is there any reason to avoid using implicit as I used it now ? It going to be deprecated ?

In Scala 3, the type of a given is the one thing that matters. It must always be written explicitly. The name can be dropped. So implicit foo => is out, you’d at least have to write something like given foo: Foo =>. But since we have already a better idiomatic solution with CFTs, there’s not need to complicate the syntax. The workarounds by @WojciechMazur and @markehammons are fine.

2 Likes