-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Implicit lambda parameter replacement for givens? #12676
-
Apologies if this has been asked before, I looked through past discussions and didn't find anything on it.
If we want to turn a lambda parameter into an implicit, we can do the following:
x.flatMap(implicit a => ... )
Givens however don't seem to have the equivalent of that. Here's what I'd like to do, assuming the parameter is an Int
:
x.flatMap(given Int => ... )
At the moment, I'm forced to define a given explicitly:
x.flatMap { a => given Int = a ... }
This however is ugly and I end up resorting back to the first example with an implicit.
Is there any plans on adding this syntactic sugar back in for givens?
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 2
Replies: 5 comments 2 replies
-
the following might work
x.flatMap(a ?=> ... )
Beta Was this translation helpful? Give feedback.
All reactions
-
for now there is this
scala> inline def givenAs[T, U](inline f: T ?=> U): T => U = t => f(using t) def givenAs[T, U](f: (T) ?=> U): T => U scala> List(1).map(givenAs(a ?=> a)) val res2: List[Int] = List(1) scala> List(1).map(givenAs(summon[Int] + 1)) val res3: List[Int] = List(2)
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 3
-
Is there any plans on adding this syntactic sugar back in for givens?
No, but an alternative to:
x.myMethod(foo => given Foo = foo bla(foo) )
is to define in Foo (inline
to make it zero-cost):
inline def foo(using foo: Foo): Foo = foo
and then one can simply write:
import Foo.foo x.myMethod(bla(foo))
This has the advantage that every user of myMethod
will refer to the given parameter with the same name instead of everyone having to give the lambda parameter a name. This is the style we use in the compiler itself for referring to the current Context: https://github.com/lampepfl/dotty/blob/54929c2398d99c2418e526ddf59efc460bb89975/compiler/src/dotty/tools/dotc/core/Contexts.scala#L59
Beta Was this translation helpful? Give feedback.
All reactions
-
To clarify: this assumes you're defining myMethod
as:
def myMethod(Foo ?=> Bla) = ...
if you don't control myMethod
or actually want it to take an explicit lambda for other reasons that won't help.
Beta Was this translation helpful? Give feedback.
All reactions
-
Having a similar case. In Scala 2, since there is no implicit function parameter, I have a lot of API that looks like
trait Cursor[T] { def step[A](body: T => A): A // no implicit function parameter in Scala 2 } trait Ref[T, A] { def apply()(implicit tx: T): A def update(value: A)(implicit tx: T): Unit }
And the use site
trait Example[T] { def ref: Ref[T, Int] def run(cursor: Cursor[T]): Unit = cursor.step { implicit tx => ref() = ref() + 1 } }
So this makes use of the convenience to prefix the lambda's parameter tx
with modifier implicit
, which has no Scala 3 equivalent. So I was thinking that this would be cursor.step { (given tx) => ... }
but apparently not. So have to resort to the Scala 2 keyword implicit
.
Beta Was this translation helpful? Give feedback.
All reactions
-
You can use pattern-bound given with a pattern-matching function. You'll need to always specify type, however
x.flatMap { case a @ given SomeType => ... } // assuming standard flatmap of `A => F[B]` // - or - // x.flatMap { case given SomeType => ... } // if you don't need the name of parameter
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 5 -
👀 3
-
Perfect, way to go.
Beta Was this translation helpful? Give feedback.