I know that one can define an operator in Scala like this :
class value(var valu:Int) {
def +(i:Int) = { this.valu + i }
def ==>(i:Int ) = { this.valu = i }
}
But I cannot seem to overload the = operator like this :
class value(var valu:Int) {
def =(i:Int) = { this.valu = i }
}
Do you know if there is any way to do this?
The syntax for making mutable objects isn't obvious and isn't encountered often because mutability is generally undesirable.
class Value(private var valu:Int) {
def update(i:Int) :Unit = valu = i
}
val v = new Value(19)
v() = 52
= is a reserved word like yield, so to use it as an identifier, you put it in backticks, though I suspect no one does that:
scala> class C(var i: Int) { def `=`(n: Int) = i = n }
defined class C
scala> val c = new C(42)
c: C = C#9efcd90
scala> c.`=`(27)
scala> c.i
res1: Int = 27
scala> c `=` 5
scala> c.i
res3: Int = 5
Compare:
scala> val yield = 2
^
error: illegal start of simple pattern
scala> val `yield` = 2
yield: Int = 2
Related
I can use apply in Scala to overload the () operator.
class A {
val arr = Array[Int](1,2,3,4,5)
def apply(i:Int) = {
arr(i)
}
}
object Main extends App {
val a = new A
println(a(0))
}
When I set the value, I can add the set method
def set(i:Int, value:Int) = {arr(i) = value}
...
arr.set(3, 10)
Does Scala allow better syntactic sugar such as arr(3) = 10 to get the same results?
You could define the update method:
scala> class A {
| val arr = Array[Int](1,2,3,4,5)
| def apply(i: Int) = {
| arr(i)
| }
| def update(i: Int, x: Int) {
| arr(i) = x
| }
| }
defined class A
scala> val a = new A
a: A = A#7d117aef
scala> a(0)
res0: Int = 1
scala> a(0) = 42
scala> a(0)
res2: Int = 42
I am Scala beginner. Below Scala code runs well, but I cannot understand it. Log shows, line 19 finally run to line 12. How could it be?
object TestClassDef {
class Person {
private var _age = 0
def age:Int = _age
def age_=(newAge: Int) = {
_age = newAge
println("age changed to " + _age) // line 12
}
}
def main(args: Array[String]) {
var p = new Person()
// p.age_=(25)
p.age = 26 // line 19
}
}
If I get your question correctly, you're surprised that the method is called when you assign the value on line 19. This is because the _= (at the end of the age function with an Int parameter) means that it's an assignment operator (also see What are all the uses of an underscore in Scala?) so it does make sense that it's called when you simply type p.age = 26.
This is mutator
def age_=(newAge: Int) = {
_age = newAge
println("age changed to " + _age)
}
So the call
p.age = 26
is converted by compiler to
p.age_=(26)
which makes call to mutator.
Mutator naming conventions from http://docs.scala-lang.org/style/naming-conventions.html
For mutators, the name of the method should be the name of the property with “_=” appended. As long as a corresponding accessor with that particular property name is defined on the enclosing type, this convention will enable a call-site mutation syntax which mirrors assignment. Note that this is not just a convention but a requirement of the language.
Also to see what compiler is creating pass -Xprint:typer to the Scala compiler. For reference the above code with this parameter generates:
package <empty> {
object TestClassDef extends scala.AnyRef {
def <init>(): TestClassDef.type = {
TestClassDef.super.<init>();
()
};
class Person extends scala.AnyRef {
def <init>(): TestClassDef.Person = {
Person.super.<init>();
()
};
private[this] var _age: Int = 0;
<accessor> private def _age: Int = Person.this._age;
<accessor> private def _age_=(x$1: Int): Unit = Person.this._age = x$1;
def age: Int = Person.this._age;
def age_=(newAge: Int): Unit = {
Person.this._age_=(newAge);
scala.this.Predef.println("age changed to ".+(Person.this._age))
}
};
def main(args: Array[String]): Unit = {
var p: TestClassDef.Person = new TestClassDef.this.Person();
p.age_=(26)
}
}
}
Scala allows non-alphanumerics in identifiers (in two ways):
case 1:
(specialcharacters)*
scala> val ##*# = 1000000
scala> val #Alpha# = 1 // mixing alphanumerics not allowed
case 2:
letter(alphanumerics)* _ (specialcharacters)*
scala> val k12? = 1 // doesn't work, _ is mandatory
scala> val k12_? = 1
scala> val k12_?*&^% = 1
scala> val k12_?Alpha = 1 // doesn't work, can't mix alphanumeric
Special cases:
Some symbols/combination-of-symbols are reserved e.g. = # <%
scala> val # = 1 // doesn't work
scala> val ### = 1 // works fine
scala> val <% = 1 // doesn't work
scala> val <%> = 1 // works fine
Some symbol-combinations are special, _= can be used in method names but not in variable names.
scala> val k_= = 1 // doesn't work
scala> def k_= = 1 // works fine
method names ending in _= are setters.
if a class/object's setter method def x_= is defined along with a parameter-less method of same name def x, then x = e is interpreted as x_=(e)
The scope of a name introduced by a declaration or definition is the
whole statement sequence containing the binding. However, there is a
restriction on forward references in blocks: In a statement sequence
s[1]...s[n] making up a block, if a simple name in s[i] refers to
an entity defined by s[j] where j >= i, then for all s[k]
between and including s[i] and s[j],
s[k] cannot be a variable definition.
If s[k] is a value definition, it must be lazy.
Edit: I am not sure Mikaël Mayer's answer actually explained everything. Consider:
object Test {
def main(args: Array[String]) {
println(x)
lazy val x: Int = 6
}
}
Here, the lazy value x definitely has to be read/evaluated before it is actually defined in the code! Which would contradict Mikaël's claim that lazy evaluation does away with the need to evaluate things before they are defined.
Normally you cannot have this:
val e: Int = 2
val a: Int = b+c
val b: Int = c
val c: Int = 1
val d: Int = 0
because value c is not yet defined at the time of the definition of a. Because a references c, all values between a and c should be lazy so that the dependency is avoided
val e: Int = 2
lazy val a: Int = b+c
lazy val b: Int = c
lazy val c: Int = 1
val d: Int = 0
This in fact translates a, b and c as objects whose value is initialized when it is read, which would be after the declaration, i.e. this would be equivalent to:
val e: Int = 2
var a: LazyEval[Int] = null
var b: LazyEval[Int] = null
var c: LazyEval[Int] = null
a = new LazyEval[Int] {
def evalInternal() = b.eval() + c.eval()
}
b = new LazyEval[Int] {
def evalInternal() = c.eval()
}
c = new LazyEval[Int] {
def evalInternal() = 1
}
val d = 0
where LazyEval would be something like the following (implemented by the compiler itself)
class LazyEval[T] {
var value: T = _
var computed: Boolean = false
def evalInternal(): T // Abstract method to be overriden
def eval(): T = {
if(computed) value else {
value = evalInternal()
computed = true
value
}
}
}
Edit
vals don't really exist in java. They are local variables or do not exist in computation. Therefore, the declaration of lazy val exists before anything is done. And remember that closures are implemented in Scala.
Your block would be rewritten as it:
object Test {
def main(args: Array[String]) {
// Declare all variables, val, vars.
var x: Lazy[Int] = null
// No more variables to declare. Lazy/or not variable definitions
x = new LazyEval[Int] {
def evalInternal() = 6
}
// Now the code starts
println(x)
}
}
You're trying to avoid references to entities which are provably uninitialized (or which are maybe uninitialized).
In a block, assignments occur in source order, but in a class template, members can be overridden and initialized early.
For instance,
{ val a = b ; val b = 1 } // if allowed, value of a is undefined
but in a template
class X { val a = b ; val b = 1 } // warning only
val x = new { override val b = 2 } with X
x.a // this is 2
class Y(override val b: Int) extends X // similarly
You also want to avoid this:
locally {
def a = c
val b = 2 // everything in-between must be lazy, too
def c = b + 1
}
Local objects are explicitly the same as lazy vals:
{ object p { val x = o.y } ; object o { val y = 1 } }
Other kinds of forward reference:
{ val x: X = 3 ; type X = Int }
The spec talks about forward references to "entities" -- a "name refers to an entity" -- which elsewhere means both terms and types, but obviously it really means only terms here.
It will let you harm yourself:
{ def a: Int = b ; def b: Int = a; a }
Maybe your mode of self-destruction must be well-defined. Then it's OK.
I'm using Scala 2.10.1 and I'm trying the define a method which will retrieve all the vals (including the inherited ones) from an object.
I have the following:
import scala.reflect.runtime.{universe => ru}
object Reflection {
val mirror = ru.runtimeMirror(this.getClass.getClassLoader)
def findVals(x: Any): Iterable[String] = {
val theType = mirror.classSymbol(x.getClass).toType
theType.members.collect({case x if x.isTerm => x.asTerm}).filter(_.isVal).map(_.name.toString)
}
}
I am testing on these two classes:
class Base {
val x = 10
}
class Child extends Base {
val y = 20
}
When calling the following code:
val x = new Child
val vs = Reflection.findVals(x)
println(vs)
The result is List(y)
For some reason, the isVal method returns false for the term corresponding to the x field from the Base class.
Can someone tell me what's the problem here? Am I doing something wrong?
Per Why don't Scala case class fields reflect as public? you should use isAccessor instead of isVal.
I'm actually using isGetter and setter to properly filter vars per your comment:
def findVals(x: Any): Iterable[String] = {
val theType = mirror.classSymbol(x.getClass).toType
val xtm = theType.members.collect({case x if x.isTerm => x.asTerm})
xtm.filter(m => m.isGetter && !xtm.exists(m.setter == _)).map(_.name.toString)
}
Results:
scala> class Base {
| var x = 10
| val xx = 2
| }
defined class Base
scala> class Child extends Base {
| val y = 3
| }
defined class Child
scala> val x = new Child
x: Child = Child#1c0026e
scala> val vs = Reflection.findVals(x)
vs: Iterable[String] = List(y, xx)
scala> println(vs)
List(y, xx)
Using SMirror:
scala> implicit val mirror = scala.reflect.runtime.currentMirror
mirror: reflect.runtime.universe.Mirror = JavaMirror with scala.tool…
scala> import net.fwbrasil.smirror._
import net.fwbrasil.smirror._
scala> class Base {
val x = 10
}
defined class Base
scala> class Child extends Base {
val y = 20
}
defined class Child
scala> val x = new Child
x: Child = Child#448593d0
scala> x.reflect.vals
res5: List[net.fwbrasil.smirror.SInstanceVal[Child]] = List(val x: scala.Int (bound to Child#448593d0), val y: scala.Int (bound to Child#448593d0))
scala> x.reflect.vals.head.get
res7: Any = 10
So, this is terribly inelegant, but it seems to work:
import scala.reflect.runtime.{universe => ru}
object Reflection {
val mirror = ru.runtimeMirror(this.getClass.getClassLoader)
val ObjectClass = classOf[java.lang.Object];
def findVals(x: Any) : Iterable[String] = findVals( x.getClass, List.empty );
def findVals(clz: Class[_], accum : Iterable[String]): Iterable[String] = {
clz match {
case ObjectClass => accum;
case _ => {
val theType = mirror.classSymbol(clz).toType
val newVals = theType.members.collect({case x if x.isTerm => x.asTerm}).filter(_.isVal).map(_.name.toString)
findVals( clz.getSuperclass, accum ++ newVals )
}
}
}
}
Then...
scala> class Base {
| val x = 10
| var z = 20
| }
defined class Base
scala> class Child extends Base {
| val y = 20
| var a = 9
| }
defined class Child
scala> val x = new Child
x: Child = Child#3093266d
scala> val vs = Reflection.findVals(x)
vs: Iterable[String] = List("y ", "x ")
scala> println(vs)
List(y , x )
It seems that, at least for now, Scala reflection looks at the Java field to determine the presence of a val, so I guess you just have to climb the class hierarchy... I'm guessing it looks for the presence of a setter to distinguish val from var. Again, not so lovely, but functional.
I want to define one (or two, depends on how you look at it) operators in scala.
Something like this : _ ==> _ | _ where the underscore stands for the arguments.
The tricky part is, that the operator should be used in an constructor to set the fields of the object.
I wrote a small example, using implicits and a wrapper object. But that approach clearly does not work.
I don't know, how i can set the fields of the current object.
In this example, every create object from type B should have set its fields to "B", 44 and "foo". The result of "B" ==> 44 | "foo" should be the same as this.a = "B"; this.b = 44; this.c = foo.
Is there a way to achieve that?
Thanks!
abstract class Top {
var a = "a"
var b = 3
var c = "c"
implicit def js2WJ(js: String) : Wrapper = {
new Wrapper(js)
}
}
case class B() extends Top
{
"B" ==> 44 | "foo"
}
class Wrapper(js: String)
{
var ju : Option[Int] = None
var cs : Option[String] = None
def ==>(j: Int): Wrapper = {
ju = Some(j)
this
}
def | (cs: String) =
{
this.cs = Some(cs)
}
}
Is this what you needed?
abstract class Top {
var a = "a"
var b = 3
var c = "c"
implicit def js2WJ(js: String): TopBuilder = TopBuilder(js, b, c, this)
}
case class TopBuilder(a: String, b: Int, c: String, top: Top) {
def ==> (j: Int) = copy(b = j)
def | (s: String) = copy(c = s) toTop
def toTop {
top.a = a
top.b = b
top.c = c
}
}
object B extends Top {
"B" ==> 44 | "foo"
}