Intro
I see a few other posts on here relating to scope injection using implicits or other things to try and get a sort of scope injection like behavior. The part that confuses me is that scala already has a feature that I would expect to work for this, but it has 2 problems.
The feature I am talking about is single abstract method
s, or SAM
. Below I detail how it seems this feature should already work right out of the box, but does not for some reason.
Some Context
Below, you can see a trait which can be implemented using a SAM
.
import scala.collection.mutable.{ListBuffer => MList}
trait DslFunction[P] {
var value: P = _
protected def run: Unit
// Technically not thread safe, but this could be easily fixed
def execute(value: P): P = {
this.value = value
run
value
}
}
The point here is not to make some special trait for this feature, but to point out the fact that you can essentially already do this with any SAM.
The Implementation
Showing how you would set it up
def a(f: DslA): A =
f.execute(A())
trait DslA extends DslFunction[A] {
def b1(f: DslB1): B1 = {
val res: B1 = f.execute(B1())
value.b1.append(res)
res
}
def b2(f: DslB2): B2 = {
val res: B2 = f.execute(B2())
value.b2.append(res)
res
}
}
trait DslB1 extends DslFunction[B1] {
def c1(f: DslC1): C1 = {
val res: C1 = f.execute(C1())
value.c1.append(res)
res
}
}
trait DslB2 extends DslFunction[B2] {
def c2(f: DslC2): C2 = {
val res: C2 = f.execute(C2())
value.c2.append(res)
res
}
}
trait DslC1 extends DslFunction[C1] {
def add(i: Int): Unit =
value.ints.append(i)
}
trait DslC2 extends DslFunction[C2] {
def add(s: String): Unit =
value.strings.append(s)
}
Awful Syntax - Works
val res0: A = a(new DslA {
override protected def run: Unit = {
b1(new DslB1 {
override protected def run: Unit = {
c1(new DslC1 {
override protected def run: Unit = {
add(1)
add(2)
add(3)
}
})
}
})
b2(new DslB2 {
override protected def run: Unit = {
c2(new DslC2 {
override protected def run: Unit = {
add("~ 1 ~")
add("~ 2 ~")
add("~ 3 ~")
}
})
}
})
}
})
Awesome Syntax - Doesn’t Work
a {
b1 {
c1 {
add(1)
add(2)
add(3)
}
}
b2 {
c2 {
add("~ 1 ~")
add("~ 2 ~")
add("~ 3 ~")
}
}
}
Whats Wrong?
There seems to be 2 issues here:
- Scala doesnt seem to recognize that you are trying to do a SAM unless there are parameters.
AKA, It seems to think I am doing something like:a(f: => Unit)
. - Even if you circumvent this by doing something like
def run(useless: Unit): Unit
a { _ => ... }
(which does get around problem #1, by the way, although it is an annoyance)
You are still left with the fact that your single abstract METHOD does not act like a METHOD whatsoever.
The first definition I found when searchingprogramming method definition
:
A method in object-oriented programming is a procedure associated with a message and an object.
Our little single abstract METHODs here dont seem to realize they are really part of a bigger picture.
As I have been informed, apparently the powers that be are opposed to implementing any sort of "scope injection"
in scala, given that it is confusing, but I would argue that this is rather intuitive. If you are filling out one last method to complete the trait, you would expect that that method knows about the rest of the trait, would you not?
Im very interested to see what everyone else has to say about this.