The main idea of that proposal is that inside a function body of apply we have a context of the ExtendedFunction class. So we can use methods,variables and implicits of that class.
It will be very useful in dsl api.
See also:
There is FunctionalInterface in the java
The documentation says :
_Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references
It works, but you have to write an actual lambda () => println("ok").
A semi-reasonable expectation could be that in
abstract class ExtendedFunction{
def execute: Unit // notice: no parameter list
}
def doSomeThing(f: ExtendedFunction):Unit = {}
f would be treated like a by-name parameter, because execute sort of has type => Unit.
Until you can convince someone of actually speccing and implementing that, and having that custom ExtendedFunction class is important to you, you could consider this alternative:
abstract class ExtendedFunction{
def execute: Unit
}
def doSomeThing(f: => Unit): Unit = {
val f0 = new ExtendedFunction {
def execute = f
}
}
doSomeThing{ new ExtendedFunction{
override def execute():Unit = {
}
}
The main idea of that proposal is that inside a function body of execute we have a context of the ExtendedFunction class. So we can use methods,variables and implicits of that class.
import scala.language.implicitConversions
object Scala {
abstract class UncleSam {
implicit def intToSet(int: Int): Set[Int] = Set(int)
def definedMethod(x: Set[Int]): String = s"x = $x"
def abstractMethod(self: UncleSam): Unit
}
def doSomeThing(lambda: UncleSam): Unit = {
lambda.abstractMethod(lambda)
}
def main(args: Array[String]): Unit = {
doSomeThing { self => // you need explicit parameter
import self._ // and explicit import from it
println(definedMethod(80))
}
}
}
There was already a proposal to define ThisFunction which would remove the need for
self =>
import self._
and you’ve posted a link to it in first post.
I would like something like the ThisFunction proposal for tests. Often I use something like:
"my class" must "do something important" in test { fixture =>
import fixture._
// rest of the test
}
Eliding whole fixture => + import fixture._ would be too disruptive for my taste, but something like:
"my class" must "do something important" in test { import fixture._ => // shortcut for previous syntax
// rest of the test with fixture contents visible in scope
}
or
"my class" must "do something important" in test { this fixture =>
// rest of the test with fixture contents visible in scope
}
The main reason we don’t do it for 0-ary SAM types is to avoid confusion when the interface is a SAM by accident (InputStream is a fun example.) We could do the expansion when the type is annotated with FunctionalInterface
@adriaanm:
IIUC that still wouldn’t have any effect on this or visibility of ExtendedFuction members. this used in function passed to doSomething would still point to Main object. Members of ExtendedFunction wouldn’t be visible inside function passed to doSomeThing. Is that correct?
I do not think there will be a reasonable sense to do ExtendedFunction if members of ExtendedFunction are not visible inside function passed to doSomeThing. I really need better DalayedInit and Builders.
Are there any difficulties to do that visability?
Is it difficult?
It’s just not what a lambda is. Its this is the class it’s contained in. Not sure about having a separate kind of function that changes the meaning of this (for one, I don’t think you could compile it to an invokedynamic lambda because these lambdas are not full classes on Java 8).
I can see the motivation for wanting to inject members into scope in a lambda, but not sure about the impact on language complexity.
Sorry I just do not understand compiler internals well, Why shoud this proposal be a lambda?
Is it possible to make sugaring or something else to treat it as:
new ExtendedFunction{ override def execute():Unit = {
println("ok")
}
If it is hard at least I will not miss this feature
class HTML() extend Tag {
def head(init: Head):Head = initTag(init)
def body(init: Body):Body = initTag(init)
}
class Head()extend Tag {
def title(init: Title):Title = initTag(init)
}
class Title() extend Tag
class BodyTag(name: String) extend Tag {
def b(init: B):Unit = initTag(init)
def p(init: P):Unit = initTag(init)
def h1(init: H1):Unit = initTag(init)
def ul(init: UL):Unit = initTag(init)
def a(href: String, init: A):Unit = initTag(init)
}
class Body extend BodyTag("body")
class UL extend BodyTag("ul") {
fun li(init: LI):Unit = initTag(init)
}
class B extend BodyTag("b")
class LI extend BodyTag("li")
class P extend BodyTag("p")
class H1 extend BodyTag("h1")
class A extend BodyTag("a") {
var href: String
}
object Html{
fun html(init: HTML): HTML = init.initTag
}
It is just impossible on “implicit function types”
Ok, we can make something similar:
class Table {
val rows = new ArrayBuffer[Row]
def add(r: Row): Unit = rows += r
override def toString = rows.mkString("Table(", ", ", ")")
}
class Row {
val cells = new ArrayBuffer[Cell]
def add(c: Cell): Unit = cells += c
override def toString = cells.mkString("Row(", ", ", ")")
}
case class Cell(elem: String)
object HtmlTable{
def htmlTable(init: implicit Table => Unit) = {
implicit val t = new Table
init
t
}
def row(init: implicit Row => Unit)(implicit t: Table) = {
implicit val r = new Row
init
t.add(r)
}
def cell(str: String)(implicit r: Row) =
r.add(new Cell(str))
}
I just do not know how it can be called a simple way.
There is context independent grammar so we have very high coupling, Methods is detached from its classes. There are very high risks of name clashes.
Ok we can always say it is not important. It is the question of priorities of cause. But I dream about such ability. It will make my life easier in jpa, html and so on