score:2
Does it mean that blocks are objects too?
No, blocks are not objects. Blocks are used for scoping the binding of variables. Scala enables not only defining expressions inside blocks but also to define methods. If we take your example and compile it, we can see what the compiler does:
object Test extends Object {
def method1(): Unit = scala.Predef.println("method 1");
private[this] val x: String = _;
<stable> <accessor> def x(): String = Test.this.x;
final <static> private[this] def method2$1(): String = "method 2";
def <init>(): tests.Test.type = {
Test.super.<init>();
Test.this.x = {
"this is ".+(Test.this.method2$1())
};
Test.this.method1();
scala.Predef.println(Test.this.x());
()
}
}
What the compiler did is extract method2
to an "unnamed" method on method2$1
and scoped it to private[this]
which is scoped to the current instance of the type.
And how are handled the statements part of an object, are they members too?
The compiler took method1
and println
and calls them inside the constructor when the type is initialized. So you can see val x
and the rest of the method calls are invoked at construction time.
score:1
method2
is actually not a method. It is a local function. Scala allows you to create named functions inside local scopes for organizing your code into functions without polluting the namespace.
It is most often used to define local tail-recursive helper functions. Often, when making a function tail-recursive, you need to add an additional parameter to carry the "state" on the call stack, but this additional parameter is a private internal implementation detail and shouldn't be exposed to clients. In languages without local functions, you would make this a private
helper alongside the primary method, but then it would still be within the namespace of the class and callable by all other methods of the class, when it is really only useful for that particular method. So, in Scala, you can instead define it locally inside the method:
// non tail-recursive
def length[A](ls: List[A]) = ls match {
case Nil => 0
case x :: xs => length(xs) + 1
}
//transformation to tail-recursive, Java-style:
def length[A](ls: List[A]) = lengthRec(ls, 0)
private def lengthRec[A](ls: List[A], len: Int) = ls match {
case Nil => len
case x :: xs => lengthRec(xs, len + 1)
}
//tail-recursive, Scala-style:
def length[A](ls: List[A]) = {
//note: lengthRec is nested and thus can access `ls`, there is no need to pass it
def lengthRec(len: Int) = ls match {
case Nil => len
case x :: xs => lengthRec(xs, len + 1)
}
lengthRec(ls, 0)
}
Now you might say, well I see the value in defining local functions inside methods, but what's the value in being able to define local functions in blocks? Scala tries to as simple as possible and have as few corner cases as possible. If you can define local functions inside methods, and local functions inside local functions … then why not simplify that rule and just say that local functions behave just like local fields, you can simply define them in any block scope. Then you don't need different scope rules for local fields and local functions, and you have simplified the language.
The other thing you mentioned, being able to execute code in the bode of a template, that's actually the primary constructor (so to speak … it's technically more like an initializer). Remember: the primary constructor's signature is defined with parentheses after the class name … but where would you put the code for the constructor then? Well, you put it in the body of the class!
Source: stackoverflow.com
Related Query
- Why is it allowed to put methods inside blocks, and statements inside objects in Scala?
- Why it doesn't allowed to overload methods inside methods (e.g. overloaded closures)?
- Why are classes inside Scala package objects dispreferred?
- Why are case objects serializable and case classes not?
- Why must forward referenced values inside blocks in Scala be lazy?
- Why are Buffer and List objects equal (even they are from different classes)?
- why both transform and map methods in scala?
- Why do these similar looking statements yield objects of different types?
- Why doesn't the scala compiler generate a warning on if statements that always yield false inside a pattern match?
- Why making a difference between methods and functions in Scala?
- Why are methods -- and - deprecated for List?
- Why do val and def implement abstract methods at different times?
- Interoperability : sharing Datasets of objects or Row between Java and Scala, two ways. I put a Scala dataset operation in the middle of Java ones
- Why do methods and types impose different constraints on variance?
- Scala: why duplicate declaration is allowed inside pattern matching?
- Why does operator associativity work differently for Scala 3 extension methods and regular methods?
- Multiple recursive calls inside if/else statements and tail recursion
- Why `floorEntry` and other methods are not accessible in PatriciaTrie?
- Scala - Declaring val fields and initializing them inside methods
- Why are classes created inside Objects in Scala
- Why do my bytes appear to get corrupted when I try to write them from inside if statements or pattern matches
- Why the two apply methods in companion objects do not work?
- When and why does Scala code needs to be on a method called main inside an object?
- Scala Controller that calls the Dao methods to get the objects and convert to json
- Why does the Scala compiler disallow overloaded methods with default arguments?
- Why doesn't the example compile, aka how does (co-, contra-, and in-) variance work?
- Why are `private val` and `private final val` different?
- What are Scala continuations and why use them?
- Why does Scala provide both multiple parameters lists and multiple parameters per list?
- When and why should one use Applicative Functors in Scala
More Query from same tag
- Scala: How to simply apply same method to all exceptions in catch block
- Scala String Interpolation with MAP Data structure
- Converting Seq[String] to String*
- Higher kind/type bound puzzler in Scala
- How to work with Scala and Jcurses?
- How to use MonadError correctly?
- Combine multiple ArrayType Columns in Spark into one ArrayType Column
- "MyType" problem: Do I have to use abstract types (or generics) in Scala to return the actual class?
- how to read a file from a lift webapp
- Replacing implementation of a trait during tests in PlayFramework?
- mixed scala/java project, which compile first?
- regex doesn't find a match if it is defined in a function
- avoid inheriting method in scala
- Scala match not working
- selecting random numbers from set of numbers without repetition
- Spray: factor out onSuccess directive
- Scala - Undo a flatmap after transformation
- Why does Source.tick stop after one hundred HttpRequests?
- Calling showdown using Rhino
- How can I assert if a class extends "AnyVal" using ArchUnit
- Spark - aggregateByKey Type mismatch error
- Scala Eclipse Autocomplete Broken?
- Scala: Spark SQL to_date(unix_timestamp) returning NULL
- Json object to map
- Apache Spark What happens when repartition($"key") is called when size of all records per key is greater than the size of a single partition?
- Implement service with play framework in which one parameter is a url
- Scala compiler not executing the values which are not returned
- What does the single-right-arrow (→) mean for collections in Scala?
- How to store different value types in scala
- 'J' icon for .scala files?