This example is from one of the Scala books:
trait IO { self =>
def run: Unit
def ++(io: IO): IO = new IO {
def run = { self.run; io.run }
}
}
object IO {
def empty: IO = new IO { def run = () }
}
The explanation given in the book is as follows:
The self argument lets us refer to this object as self instead of this.
What would that statement mean?
self is just an alias to this in the object in which it is declared, and it can be any valid identifier (but not this, otherwise no alias is made). So self can be used to reference this from an outer object from within an inner object, where this would otherwise mean something different. Perhaps this example will clear things up:
trait Outer { self =>
val a = 1
def thisA = this.a // this refers to an instance of Outer
def selfA = self.a // self is just an alias for this (instance of Outer)
object Inner {
val a = 2
def thisA = this.a // this refers to an instance of Inner (this object)
def selfA = self.a // self is still an alias for this (instance of Outer)
}
}
object Outer extends Outer
Outer.a // 1
Outer.thisA // 1
Outer.selfA // 1
Outer.Inner.a // 2
Outer.Inner.thisA // 2
Outer.Inner.selfA // 1 *** From `Outer`
Related
Suppose I have the following:
class Deck[+T] {
class Card(value: T)
class Pile(val cards: List[Card]) {
val deck = Deck.this
def shuffle(shuffler: Shuffler): shuffler.shuffle(this)
}
}
trait Shuffler {
def shuffle[T](pile: Deck[T]#Pile): pile.type
}
object Shuffler {
def randomShuffler(r: Random): Shuffler = new Shuffler {
override def shuffle[T](pile: Deck[T]#Pile): pile.deck.Pile = {
new pile.deck.Pile(r.shuffle(pile.cards))
}
}
}
Is it possible to do the same thing without having the val deck declaration in Pile? Also, is it possible to do the same thing without the T declaration in shuffle()?
I had been playing around with things such as pile: x.Pile forSome {val x: Deck[_]}, but they don't seem to compile due to typing issues (read: me not fully understanding semantics therein), and I'm trying to avoid rewriting Shuffler to, say, work with raw lists instead (how do I express that, anyways? List[Deck[T]#Card] is not quite there, since I want lists of Cards from the same Deck).
Is it possible to do the same thing without having the val deck declaration in Pile?
Not if we want to enforce a value dependent type, which you seem to want (e.g. two Pile[Int] being only compatible if they refer to the same deck value).
Also, is it possible to do the same thing without the T declaration in shuffle()?
You can move type parameters to type members, this can sometimes save you from needing to specify them when they are only internally used.
Here is an idea:
object Pile {
def apply(deck0: Deck): Pile { type D = deck0.type } = new Pile {
val deck = deck0
type D = deck0.type
val cards = deck.cards.toList
}
}
trait Pile { self =>
type D <: Deck
type Self = Pile { type D = self.deck.type }
val deck : D
def cards: List[deck.Card]
def shuffle(shuffler: Shuffler): Self = shuffler.shuffle(this)
}
object Deck {
def apply[A1](values: Set[A1]): Deck { type A = A1 } = new Deck {
type A = A1
val cards = values.map(Card(_))
}
}
trait Deck {
type A
case class Card(value: A)
def cards: Set[Card]
}
trait Shuffler {
def shuffle(pile: Pile): pile.Self
}
object Shuffler {
def randomShuffler(r: util.Random): Shuffler = new Shuffler {
def shuffle(pile: Pile): pile.Self = new Pile {
type D = pile.deck.type
val deck = pile.deck
val cards = r.shuffle(pile.cards)
}
}
}
Test:
val deck = Deck(Set(1 to 10: _*))
val pile0 = Pile(deck)
pile0.cards
val sh = Shuffler.randomShuffler(util.Random)
val pile1 = pile0.shuffle(sh)
pile1.cards
As you can see, enforcing value dependent types is not trivial, so the question is if you really need them, or you are ok with a simple type parameter for A. For example, the above doesn't prevent you from accidentally putting the same card twice into a pile.
I would like to create a framework where users are able to subclass a base class, Node which is able to produce a message (here an integer) based on the current instance state, and the properties of another instance (the parameter n). The users should be able to specialize the method getMessage to produce different messages based on the class of the current instance and the class of the parameter n, as shown in the code below.
The function importantAlgorithm uses messages generated by these nodes to compute the final results.
// Classes defined by the framework //
abstract class Node {
def getMessage(n: Node) : Int
}
def importantAlgorithm(lstNodes1: List[_ <: Node], lstNodes2: List[_ <: Node]) = {
val results = lstNodes1.zip(lstNodes2).map({case (n1, n2) =>
// I would like to get the proper message *BASED ON
// THE TYPE OF N1 and N2*
val message = n1.getMessage(n2)
// Do some work with the message
//...
//...
})
//...
}
// Classes defined by framework users //
class ItemNode(val p: Int) extends Node {
override def getMessage(n: UserNode) = {
// Compute message based on this ItemNode member variables
// and n (instance of UserNode) member variables
}
override def getMessage(n: ItemNode) = {
// Compute message based on this ItemNode member variables
// and n (instance of UserNode) member variables
// The algorithm is different from the algorithm
// used in the previous method
}
}
class UserNode extends Node {
override def getMessage(n: OtherNode) = {
// Compute message. Same idea as above
}
}
class OtherNode extends Node {
override def getMessage(n: UserNode) = {
// Compute message. Same idea as above
}
}
// The user should be able to use the framework this way
importantAlgorithm(List(new UserNode(), new ItemNode(236), new OtherNode(),
List(new OtherNode(), new ItemNode(542), new UserNode()))
Of course, Scala does not allow to specialize a parameter of a method in a subclass and the above code does not compile. I could use isInstanceOf[] or RTTI but I have a feeling that I am not thinking properly and not designing my framework properly. How could I replace the mechanism described in the code sample above by a simpler and cleaner solution ?
Would this suffice? (It compiles...)
/* Classes defined by the framework */
abstract class Node {
def getMessage(n: Node): Int
}
def importantAlgorithm(lstNodes1: List[Node], lstNodes2: List[Node]) {
lstNodes1.zip(lstNodes2).map {
case (n1, n2) =>
// I would like to get the proper message *BASED ON
// THE TYPE OF N1 and N2*
val message = n1.getMessage(n2)
}
}
/* Classes defined by framework users */
class ItemNode(val p: Int)
extends Node
{
def getMessage(n: Node): Int =
n match {
// Compute message based on this ItemNode member variables
// and n (instance of UserNode) member variables
case un: UserNode => 0
case in: ItemNode => 1
case xn: Node => -1
}
}
class UserNode
extends Node
{
def getMessage(n: Node): Int =
n match {
case on: OtherNode => 23
case xn: Node => -1
}
}
class OtherNode
extends Node
{
def getMessage(n: Node): Int =
n match {
case xn: Node => 514
}
}
// The user should be able to use the framework this way
importantAlgorithm(List(new UserNode(),
new ItemNode(236),
new OtherNode()),
List(new OtherNode(),
new ItemNode(542),
new UserNode()))
I think you need is something like
trait Node {
type AppropriateSender <: Node
def getMessage(n: AppropriateSender): Int
}
class UserNode extends Node {
type AppropriateSender = OtherNode
def getMessage(n: OtherNode) = ???
}
...
However, there are some problems caused by type erasure so that you cannot check the compatibility of your n1 and n2 (maybe type tags?), but at least you can implement your staff in a clean way now. Another issue is how you deal with the fact that some node types have more than 1 appropriate sender type (which might be solved by an implementation of raw union type).
I am trying to replicate my problem on a smaller example.
I am getting compilation error at the shown location in the following code snippet.
class Outer {
class Inner
}
object OuterUtil {
val obj = new Outer
object xyz extends obj.Inner
//do something with xyz
}
//-------------------
object OuterUtil2 {
var m_obj: Outer = null
def createOuter() = {
m_obj = new Outer
}
def anotherMethod() {
//Compilation error here: stable identifier required,
//but OuterUtil2.this.m_obj found.
object xyz extends m_obj.Inner
}
}
object Test {
OuterUtil2.createOuter
OuterUtil2.anotherMethod
}
OuterUtil is working fine.
In OuterUtil2, I am splitting the functionality into two functions. I am storing the Outer instance m_obj as a member var. The createOuter method creates and stores the Outer instance in m_obj. In anotherMethod, I am getting compilation error. How to fix OuterUtil2?
The prefix of a type (ie, the m_obj in m_obj.Inner) must be a stable value; a var doesn't cut it. You could make that a val and move the initialization out of createOuter.
If you just want to solve the problem with your function, here is a solution (by fixing the var to a val in the function)
def anotherMethod = {
val obj = m_obj
new obj.Inner
}
Another solution would be to use some options, however to overpass the stable identifier method, you have to define a val out of m_obj value. This solution is more elegant because you don't have null pointer exceptions if m_obj is not defined.
object OuterUtil2 {
var m_obj: Option[Outer] = None
def createOuter {
m_obj = Some(new Outer)
}
def anotherMethod = {
m_obj match{
case None => None
case Some(_) => val obj = m_obj.get; Some(new obj.Inner)
}
}
}
As far as I understand it, Scala creates an anonymous class if I create a class using the new keyword and follow the class name with a constructor:
class MyClass {
def doStuff() {
// ...
}
}
val mc = new MyClass {
doStuff()
}
The nice thing being that all the code in the constructor is in the scope of the new object.
Is there a way I can reproduce this syntax where the class is created by a factory method rather than the new keyword? i.e. make the following code work:
val mf = new MyFactory
val mc = mf.MyClass {
doStuff()
}
I can't find a way to do it but Scala has so much to it that this might be pretty easy!
Using an import as suggested by #Ricky below I can get:
val mf = MyFactory;
val mc = mf.MyClass
{
import mc._
doStuff()
}
(Where the blank line before the block is needed) but that code block is not a constructor.
You can do this, but you still have to keep the new keyword, and create the nested class as a path-dependent type:
class Bippy(x: Int) {
class Bop {
def getIt = x
}
}
val bip = new Bippy(7)
val bop = new bip.Bop
bop.getIt // yields 7
val bop2 = new bip.Bop{ override def getIt = 42 }
bop2.getIt // yields 42
I don't think it's possible. However, a common pattern is to add a parameter to factory methods which takes a function modifying the created object:
trait MyClass {
var name = ""
def doStuff():Unit
}
class Foo extends MyClass {
def doStuff() { println("FOO: " + name) }
}
trait MyClassFactory {
def make: MyClass
def apply( body: MyClass => Unit ) = {
val mc = make
body(mc)
mc
}
}
object FooFactory extends MyClassFactory {
def make = new Foo
}
You can then create and modify instance with a syntax close to your example:
val foo = FooFactory { f=>
f.name = "Joe"
f.doStuff
}
It sounds like you're just looking to mix in a trait. Instead of calling myFactoryMethod(classOf[Foo]] which ideally would do (if Scala permitted it):
new T {
override def toString = "My implementation here."
}
you can instead write
trait MyImplementation {
override def toString = "My implementation here."
}
new Foo with MyImplementation
However, if you are just looking to get the members of the new object accessible without qualification, remember you can import from any stable identifier:
val foo = new Bar
import foo._
println(baz) //where baz is a member of foo.
ZeroC Ice for Java translates every Slice interface Simple into (among other things) a proxy interface SimplePrx and a proxy SimplePrxHelper. If I have an ObjectPrx (the base interface for all proxies), I can check whether it actually has interface Simple by using a static method on SimplePrxHelper:
val obj : Ice.ObjectPrx = ...; // Get a proxy from somewhere...
val simple : SimplePrx = SimplePrxHelper.checkedCast(obj);
if (simple != null)
// Object supports the Simple interface...
else
// Object is not of type Simple...
I wanted to write a method castTo so that I could replace the second line with
val simple = castTo[SimplePrx](obj)
or
val simple = castTo[SimplePrxHelper](obj)
So far as I can see, Scala's type system is not expressive enough to allow me to define castTo. Is this correct?
Should be able to do something with implicits, along these lines:
object Casting {
trait Caster[A] {
def checkedCast(obj: ObjectPrx): Option[A]
}
def castTo[A](obj: ObjectPrx)(implicit caster: Caster[A]) =
caster.checkedCast(obj)
implicit object SimplePrxCaster extends Caster[SimplePrx] {
def checkedCast(obj: ObjectPrx) = Option(SimplePrxHelper.checkedCast(obj))
}
}
Then you just bring things into scope where you want to use them:
package my.package
import Casting._
...
def whatever(prx: ObjectPrx) {
castTo[SimplePrx](prx) foreach (_.somethingSimple())
}
...
You can get something like what you want with structural types:
def castTo[A](helper: { def checkedCast(o: Object): A })(o: Object) = {
helper.checkedCast(o)
}
class FooPrx { }
object FooPrxHelper {
def checkedCast(o: Object): FooPrx = o match {
case fp : FooPrx => fp
case _ => null
}
}
scala> val o: Object = new FooPrx
o: java.lang.Object = FooPrx#da8742
scala> val fp = castTo(FooPrxHelper)(o)
fp: FooPrx = FooPrx#da8742