https://kotlinlang.org logo
Title
t

Tristan Hamilton

12/01/2020, 4:46 PM
Messing around with functional interfaces. I was curious to see if they would work instead of using a function literal with receiver when trying to scope an extension function to a particular context. Not saying we should be able to do this, just thought it was interesting and if people had thoughts on it. I'm guessing it would be slower since you lose the ability to 
inline
 the lambda. Any reasons why you may want to write it this way over a receiver?
fun myScopedIntFunction(block: MyCustomIntFunctionScope): Int {
  return block.receive()
}

fun interface MyCustomIntFunctionScope {
  fun receive(): Int

  fun Int.plusThree(): Int {
    return this + 3
  }
}

fun main(){
  myScopedIntFunction {
      1.plusThree()  //won't compile
  }
  object: MyCustomIntFunctionScope {
      override fun receive(): Int {
          return 1.plusThree()
      }
  }.receive()      //works
}
r

raulraja

12/02/2020, 9:49 AM
I think it's a great technique to derive other methods polymorphic in the fun interface. We are using this in a similar way and I think you can still inline if the derived methods are inlined extensions. This is what I was proposing for arrow. 1.0 https://gist.github.com/raulraja/e732bdaace04426d3be4380b7760a8c0
👀 1
I have not found yet a case where members with receivers are needed but I guess it depends on the public api one is building. I still found using those we need to call type.run { } to get them in scope
👍 1
t

Tristan Hamilton

12/02/2020, 4:53 PM
I had spotted you shared this in the arrow channel. Looks really interesting. Would love to see a talk on all of this in action! will be attending the remote 8 meetup, will this stuff feature or is the topic slightly different? One line I'm finding hard to read is L55 of instances particularly
{ EitherEffect { it } }
what exactly is happening here?
r

raulraja

12/02/2020, 5:54 PM
I’m speaking this Fridat at Jlove and in the 10th at Lambda Lille about building Effect blocks and this particular encoding for Either but not touching on Type classes or the Functor hierarchy. The talk aims to show people how they can build their own computation Effects based on the arrow-continuations library and how we use it in Arrow to encode one of the use cases which is monad bind. It includes the effect interface and I will explain how we leverage fun interfaces to in this case push the scope impl to the edge but build on it for the Effect instance
🙇‍♂️ 1
What’s happening in line 55 is that
it
is a delimited scope in which
shift
relied for the either impl but is deferred all the way to the end so it can support multiple strategies, suspended, restricted, multishot etc.
making Effect a fun interface allows us to push the delimited scope impl to the final function that constructs the computation block
Reset.suspended { Right(f(EitherEffect { this /* this is DelimitedScope<Either<E, A>> */ }) }
is another way to implement the computation explicitly
j

julian

12/16/2020, 6:36 AM
@raulraja You said
I think it's a great technique to derive other methods polymorphic in the fun interface.
Can you explain this a bit more, or point to an example in the gist you shared where this is done? I don't understand what it means to "derive other methods polymorphic in the fun interface". Thanks!
r

raulraja

12/16/2020, 9:22 AM
@julian derive it’s perhaps not the best word, I ment that as in the example here, even though
fun interface
takes a single abstract method you can still define the rest of the interface methods as extensions and delegate to the polymorphic implementation to avoid implementing it concretely. It’s just a nice thing but most likely we won’t have that fun interface for Functor in Arrow. In whatever case you can see there how the fun interface matches the Either::map function which is the only one the data type needs to implement in this case.
j

julian

12/16/2020, 3:52 PM
Wow, this is really cool how the parts are built up into the final
fproduct
! Thanks for explaining @raulraja!