Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Implicit lambda parameter replacement for givens? #12676

qwbarch started this conversation in General Discussion
Discussion options

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?

You must be logged in to vote

Replies: 5 comments 2 replies

Comment options

the following might work

x.flatMap(a ?=> ... )
You must be logged in to vote
0 replies
Comment options

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)
You must be logged in to vote
0 replies
Comment options

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

You must be logged in to vote
1 reply
Comment options

smarter Jun 2, 2021
Collaborator

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.

Comment options

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.

You must be logged in to vote
0 replies
Comment options

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
You must be logged in to vote
1 reply
Comment options

Perfect, way to go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

AltStyle によって変換されたページ (->オリジナル) /