Idiom for creating a scoped value only once in scala - scala

Say I define a function that declares a variable in its body thus:
def foo = {
val x = new X()
x.bar
}
Is there a way I can do this such that x is only created once no matter how many times I call the function? In other words can I achieve:
val x = new X()
def foo = {
x.bar
}
but keep the definition of x within the scope of the function?

You cannot do that. If your variable is declared inside a block B. This variable cannot be seen outside B.
What you can do, is to make a class or an object to make an attribut visible outside of a definition.
object CoolObject {
val x = new X()
def foo = {
// [...]
x.bar
// [...]
}
}

If x is truly singleton, then you need to put it into a singleton context. The Scala way to do this is to create an object.
object xHolder {
val x = new X()
}
...
def foo = {
import xHolder._
x.bar
}
If foo is part of a class that has a companion object, you could put it there as well.

Related

Can't understand path dependent type

For a class C, you can use the familiar this inside the body to refer to the current instance, but this is actually a shorthand for C.this in Scala:
class C {
var x = "1"
def setX1(x:String) = this.x = x
def setX2(x:String) = C.this.x = x
}
I just can't understand C.this, C is a class, I can't understand why we use dot between C and this as shown in C.this?
I can't understand why we use dot between C and this as shown in
C.this
Using the class name before this is called a Qualified this in Java (see Using "this" with class name) and is similar in Scala. You use it when you want to reference an outer class from an inner class. Let's assume for example that you had a method declaration in your C class where you wanted to call this and mean "the this reference of C:
class C {
val func = new Function0[Unit] {
override def apply(): Unit = println(this.getClass)
}
}
new C().func()
Yields:
class A$A150$A$A150$C$$anon$1
You see the anon$1 at the end of the getClass name? It's because inside the function instance this this is actually of the function class. But, we actually wanted to reference the this type of C instead. For that, you do:
class C {
val func = new Function0[Unit] {
override def apply(): Unit = println(C.this.getClass)
}
}
new C().func()
Yields:
class A$A152$A$A152$C
Notice the C at the end instead of anon$1.

How to add instance name to String using this-keyword?

I'm searching for quite a while to get around the following problem:
Every instance of my class "B" uses a method to store a Seq "output" in a file.
class B extends IO {
private var b = 0.0
var output = Seq(0.0)
def add(a:Int) = {
b += a
output :+= b
WriteToFile(fileName, output)
}
}
And theres also a trait where the WriteToFile-method is:
trait IO {
def WriteToFile(fileName:String, data:Seq[Int]) = {
create file and name it something like: fileName+this+".m"
}
}
So every time the method "add" is called on an instance on class "B", the output-sequence is stored in a file. I want to create a different file for every instance of class "B". But when I create an instance like
val x = new B
the this-keyword in the WriteToFile-Method just adds "Bank()" to the fileName. So, how can alter the code in such a way that every new instance of class "B" creates its own file? And how can I alter the WriteToFile-Method in such way that the name of the instance (here "x") is added to the String determining the fileName?
I'd discourage you from trying naming object instances according to the names of your variables. Variables are very different from references. For example, let's have this piece of code:
def foo: Object = {
val x = new Object;
val y = x;
return x;
}
This method creates some new Object. The reference to the object is assigned to variable x and then to variable y. So now we have one objects, but referenced by two variables. And when the method returns, the object still exists, but perhaps with variable referencing it.
So naming the object by a variable that's holding it isn't very meaningful - there can be multiple such variables, or none, and it changes during the lifetime of the object.
Instead, I'd suggest you to create your own mechanism for generating names. One possibility is to use an atomic counter (so that it can be safely used from multiple threads):
trait AtomicName {
val name = "prefix" + AtomicName.newId;
}
object AtomicName extends App {
import java.util.concurrent.atomic.AtomicInteger;
private val counter = new AtomicInteger(0);
protected def newId = counter.getAndIncrement;
}
Now everything extending AtomicName will have a unique name.
trait IO {
def myName =
this.getClass.getName.split("\\$",-1).dropRight(1).lastOption.getOrElse("")
}
class B extends IO {
var output = Seq(0.0)
}
object x extends B {
def test { println(myName + " has " + output) }
}
Note that you must use object x instead of val x, and this does contain some overhead, plus it is lazy--x gets created the first time its contents are used, not the first time it's stated. (If you call myName on something that is not an object, it will give you an empty string.)
I think this is a bad idea, but this is how to do it.

Accessing to methods of case classes

Why I can't access to methods of case class inside method of ordinary class when I initiate case class instance without new keyword?
I.e. in the following code I get a compile-time error:
case class A() {
private var _g = 12
//getter-setter
def g = _g
def g_=(value : Int) = this._g = value
}
class B {
def someMethod = {
val aInstance = A
aInstance.g = 4; // compile time error. Why?
}
}
But if I add new keyword in aInstance declaration all work fine.
Error message is:
Cannot resolve symbol g
You need to make an instance of class A with A() (which calls apply on A). Otherwise you're referring to the companion object itself.
How about this? You did not define f and meant probably aInstance.
class B {
def someMethod = {
val aInstance = A
aInstance.g = 4
}
}

How to start the object

i need help with this code.
object test {
var list : Vector[MyType] = null
}
object foo extends MyType { // Mytype is a trait
println("TEST ")
test.list.:+(foo)
def myfunc() { //need to define this as this is there in the trait
// i do some operations
}
}
object Bar extends MyType { // Mytype is a trait
println("TEST ")
test.list.:+(Bar)
def myfunc(){
// i do some operations
}
}
now i want to go through the list and call myfunc() for all the objects that are extending MyType.
test.list foreach( t2 => t2.myfunc() )
the value's are not getting added to the list. Can someone let me know what i am doing wrong. Its not working. Is there a way to get that print statement working?
Your problem is, that the object is not constructed as a class, so that the code is called automatically. You could do two things. Either you extend App and call main or you write a function.
trait X
object test {
var list = Vector.empty[X]
}
object Foo extends App with X {
test.list :+= Foo
override def toString() = "Foo"
}
object Bar extends X {
def add() {
test.list :+= Bar
}
override def toString() = "Bar"
}
Foo.main(null)
Bar.add()
test.list foreach println
This code prints:
Foo
Bar
Extending App only adds a main methode to an object, containing all the code in the object.
You need to initialize test with an empty Vector rather than null. The way to do that in Scala is to use the factory method from the Vector object, and let type-inference do its job. For example:
var list = Vector.empty[MyType]
As you get the practice of doing that, you'll find yourself more focused on creating the data than on declaring its type, which in this case would have resolve this error before it happened.
Next the operation
test.list.:+(foo)
will not update test.list because, since Vector is immmutable, this method just returns a new updated copy and cannot affect the reference of list.
Try instead
test.list = test.list.:+(foo)
// or (with more idiomatic operator notation)
test.list = test.list :+ foo
// or (using syntactic sugar)
test.list :+= foo

Is there any way to extend an object?

In scala, we cannot extend object:
object X
object Y extends X
gives an error error: not found: type X
In my case someone has defined some functionality in an object and I need to extend it (basically add another method). What would be the easiest way to extend this object?
As so often the correct answer depends on the actual business requirement. Extending from an object would in some sense defy the purpose of that object since it wouldn't be a singleton any longer.
What might be a solution is to extract the behavior into an abstract trait. And create objects extending that trait like so:
trait T{
// some behavior goes here
}
object X extends T
object Y extends T {
// additional stuff here
}
If you want use methods and values from another object you can use import.
object X{
def x = 5
}
object Y{
import X._
val y = x
}
You can't actually extend an object, because that would create two of it, and an object by definition exists only once (edit: well, that's not quite true, because the object definition can be in a class or method).
For your purposes, try this:
object X {
}
object Y {
def a = 5
}
implicit def xToY(x: X.type) = Y
println(X.a)
It doesn't actually extend, but it does allow you to call new methods on it than were originally defined.
The only way to share code between two objects is by having one or more common superclass/trait.
Note that starting in Scala 3, you can alternatively use composition (instead of inheritance) via export clauses which allow defining aliases for selected members of an object:
object X { def f = 5 }
object Y {
export X._
def g = 42
def h = f * g
}
Y.f // 5
Y.g // 42
Y.h // 210
Note that you can also restrict which members you want to export:
object X { def f = 5; def g = 6 }
object Y { export X.f }
Y.f // 5
Y.g
^^^
value g is not a member of Y
You can convert parent into class + companion object, and then have child extend class E.g.
in Parent.scala
class Parent {}
object Parent extends Parent {}
And then in Child.scala
object Child extends Parent {}
Yes, it's more a hack than a solution.
This is a Scala 3 of Owen's answer: You can extend a companion object using extensions.
object X:
def a = 5
end X
// Somewhere else, another file where X is visible
extension (x: X.type)
def b = 42
end extension
// Somewhere else, another file where
// both X and the extension are visible
#main def main =
println(X.a)
println(X.b)