I have my case class:
case class MyClass(param : String)( body : => Unit) {
def save(){ ... }
def mymethod(){ ... }
body
save
}
then I want to use it like this:
MyClass("param"){ // this function can not see 'mymethod' ---
... |
mymethod() // <
...
}
Is there possible to make function 'body' be able to access 'mymethod'(and all others methods of class MyClass) ?
Why did you want this?
I see two possibilities:
Give your 'body' function a context argument:
case class MyClass(param : String)( body: MyClass => Unit) {
def mymethod() = println("MyClass.mymethod()")
body(this)
}
MyClass("test"){ ctx =>
ctx.mymethod()
}
or
Put your utility functions in MyClass companion object:
object MyClass {
def mymethod() = println("MyClass.mymethod()")
}
case class MyClass(param : String)( body: => Unit) {
body
}
MyClass("test"){
import MyClass._
mymethod()
}
Generically no. The usual approach to building a DSL is to use some kind of "command" objects, perhaps with the Free Monad:
object MyClass {
sealed trait Command
case class CallMyMethod() extends Command
def myMethod() = liftF[Command, Unit](CallMyMethod())
}
case class MyClass(param: String)(body: Free[Command, Unit]) {
...
body.resume.fold({
case CallMyMethod() => mymethod()
}, _ => {})
...
}
Then you can write your DSL "programs" using for/yield syntax:
import MyClass._
MyClass("param")({
for {
_ <- myMethod()
a = someNonMyClassCall()
b <- someOtherMyClassMethod(a)
} yield {}
})
Note that outside classes can create the CallMyMethod objects (since they're on the companion object), but that's fine, they "don't mean anything" until they're "interpreted" by the MyClass instance.
Related
I have a question about Template parameters in Scala with Case Classes.
First working scenario then what I try to achive
object Test1 {
sealed trait Response
final case class StateResponse(state : Any) extend Response
}
abstract class Test1[STATE] {
def something() : Unit = {
...
}
}
Now if use this in the following
import Test1._
result match {
case StateResponse(state) => ...
case _ => ...
}
Everything works fine but probably see what disturbs me, 'Any' at StateResponse. Depending on the implementation class I would like to have concrete State Type then any so..
object Test1Impl {
sealed trait State
final case class Test1State(payload: Map[String, String])
}
class Test1Impl extends Test1[Test1State] {
}
as you might guess I can't use Template parameter in Test1 in Object Definition but I thought, if I define the case class in class definition, it might work....
object Test1 {
sealed trait Response
}
abstract class Test1[STATE] {
final case class StateResponse(state : STATE) extends Response
def something() : Unit = {
.....
}
}
now until now, Scala Compiler does not complain about anything but when I try
import Test1._
result match {
case StateResponse(state) => ...
case _ => ...
}
then it can't locate 'StateResponse' at case statement and 'Test1.StateResponse' is not helping, so I am doing something illegal, but what?
Or can you tell me how can I make this work?
Thx for answers....
One way is to make StateResponse generic rather than enclosing class
final case class StateResponse[STATE](state : STATE) extends Response
Otherwise, when you make Test1 generic, an instance of StateResponse starts to depend on an instance of Test1
val t = new Test1[Int] {} // you made Test1 abstract, so I had to write {}
val result = t.StateResponse(10)
result match {
case t.StateResponse(state) => println("1")
case _ => println("2")
}
or
import t._
val result = StateResponse(10)
result match {
case StateResponse(state) => println("1")
case _ => println("2")
}
In this code, the parameter a in B is different from the A.a
class A(var a:String)
class B(a:String) extends A(a) {
println(a) // Use B.a
def p() {
println(a)
}
}
val b=new B("abc")
b.p() // "abc"
b.a="def"
b.p() // "abc" and not "def"
I can rename the parameter in B like this :
class B(_a:String) extends A(_a) {
println(_a) // Use B.a
def p() {
println(a)
}
}
but I would like to maintain the name 'a', for the Scaladoc, and compatibility with the syntax B(a="def").
How I can resolve this scenario ?
You can make the primary constructor private and add a secondary constructor which has a as the name:
class B private (_a:String, ignore: Unit) extends A(_a) {
def this(a) { this(a, ()) }
println(_a) // Use B.a
def p() {
println(a)
}
}
But this seems like it could easily lead to confusion. So I'd look for alternative designs, as the comments to the question suggest.
How does it should accept a String and then a function without parenthesis :
import org.scalatest.FlatSpec
import scala.collection.mutable.Stack
class StackSpec extends FlatSpec {
it should "pop values in last-in-first-out order" in {
}
}
why should it not be :
it(should("pop values in last-in-first-out order" in {
}))
Closest I came to allowing similar to compile is :
object st {
class fs {
def it(f: => Unit) = {
}
def should(s: String)(f: => Unit): Unit = {
Unit
}
it(should("pop values in last-in-first-out order") {
})
}
}
The . to call functions of objects and the () around the parameters of functions are optional in scala. So the trick is the return objects in a chain which implement functions providing the api you want. Simple example:
object InObj {
def in(func : => Unit) = func
}
object ShouldObj {
def should(x: String) = InObj
}
trait It {
def it = ShouldObj
}
class MyClass extends It {
val f = it should "Do something" in {
}
}
Scala has certain rules how operators and infix method names are converted into method calls.
it should "foo" in {}
is converted into
it.should("foo").in({})
In the case where you do not use "it" but some String a implicit conversion from String to some wrapper helps to provide the should-method.
Let's say I have a few classes class and all they extend Response(response), that is to say, have the same constructor:
import scalaj.http.Http
class MyClass1(response: Http.Request) extends Response(response) {
//....
}
class MyClass2(response: Http.Request) extends Response(response) {
//....
}
How do I create a generic method which accepts only a type of the classes above and call its constructor:
def myGeneric[A <: ???](r: Http.Request) = {
new A(r) // doesn't compile
}
I'd like to call it like this:
myGeneric[MyClass1](r) // r is Http.Request
I can do this:
def myGeneric[A <: ???](r: Http.Request)(f: r => A) = {
f(r) // f - is the constructor
}
myGeneric[MyClass1](r) { x =>
new MyClass1(x)
}
But is there more elegant way to achieve the same?
Maybe you could make myGeneric take a factory as the implicit parameter. For example:
def myGeneric[A](r: Request)(implicit f: Request => A) {
... val a = f(r) ...
If I remember right, bare implicit functions like that can get confusing, so maybe ...
trait MyFactory[T] {
def make(r: Request): T
}
...
def myGeneric[A](r: Request)(implicit f: MyFactory[A]) ...
// which is same as...
def myGeneric[A : MyFactory](r: Request) ...
I'm using the Akka actors library here. The actors library defines a partial function "receive" which an actor that extends "actor" must implement to deal with various messages. I am creating a trait hierarchy for my application where trait "clockActor" extends Actor and "MasterClock" and "SubClock" extend "clockActor". I'm looking to add the common functionality of clocks in to the "clock" trait's receive function but then how to I add extra functionality to the receive function in the master and sub clock traits?
In short, I need a way to add extra case statements to a partial function.
Ideas?
As already suggested, you could easily compose PartialFunctions using orElse
trait ClockActor {
def commonOp = {
case ... => ...
}
}
class MasterClock extends Actor with ClockActor {
def receive = commonOp orElse masterOp
def masterOp = {
case ... => ...
}
}
class SubClock extends Actor with ClockActor {
def receive = commonOp orElse subOp
def subOp = {
case ... => ...
}
}
One thing that comes to mind is to do something like this:
trait ClockActor {
def pf:PartialFunction[String, Boolean] = {
case "a" => true
case v if(_pf.isDefinedAt(v)) => _pf.apply(v)
}
def _pf:PartialFunction[String, Boolean] = Map.empty
}
object MasterClock extends ClockActor {
override def _pf:PartialFunction[String, Boolean] = {
case "b" => false
}
println(pf("a"))
println(pf("b"))
}
which will output:
scala> MasterClock
true
false
The value true comes from the definition in the partial function of the Trait ClockActor, the falsecomes from the Object MasterClock.