Why do IntelliJ worksheets mess with the class name? - scala

You would think a class named "Foo" would actually be named "Foo", but apparently not:
class Foo {
val bar = 5
val name = this.getClass.getName
def pkg = this.getClass.getPackage.getName
}
val q = new Foo()
println(s"The name is ${q.name}")
However, it is not:
defined class Foo
q: Foo = Foo#31e64c64
The name is $line111.$read$$iw$$iw$Foo
Can anyone explain what the IntelliJ Scala Worksheet is doing here?
(And if you were wondering, pkg: String = $line111)

It looks like the Worksheet uses a similar approach to the Scala REPL, namely to wrap each line into a separate, nested object.
The reason this is done this way, is that by the standard Scala semantics, a lot of things you would want to do in a REPL / Worksheet would be illegal. For example, you want to redefine a class when you realize you made a mistake:
class Foo {
def baR(x: Int) = x
}
// Oops! Typo.
class Foo {
def bar(x: Int) = x
}
// error: Foo is already defined as class Foo
// class Foo {
// ^
If the REPL or Worksheet had the same semantics as Scala, you wouldn't be able to fix typos, redefine vals, etc. Therefore, the code is instead compiled as if each line / declaration were a separate object, with some clever nesting, and importing.

Related

Scala: How to define the default value for a constructor parameter within the companion object?

The following Scala code does not compile in the Scala REPL 2.11.6:
object Foo {
val DefaultSize: Int = 10
}
class Foo(size: Int = Foo.DefaultSize)
The compile error is:
value DefaultSize is not a member of object Foo
class Foo(size: Int = Foo.DefaultSize)
Tested with Scala 2.11. This is particularly strange, since it follows exactly the accepted answer (in year 2012) here: Use method return value as default constructor parameter in Scala, which nowadays does not compile, neither. So how to achieve the intended behavior?
As explained in Programming in Scala, this is because the Scala REPL creates a new nested scope for each new statement you type in. This implies your code is interpreted as:
object Foo {
val DefaultSize: Int = 10
}
{
class Foo(size: Int = Foo.DefaultSize)
}
While the same book mentions that both the class and its companion object must be defined in the same source file, it seems that they furthermore must be in the same scope, since the code block above does not compile with scalac.
I know two ways to work around this in the REPL. As mentioned by others, you could enter :paste mode before defining the class and companion object. Alternatively, you could put both into the same scope, e.g., by defining them inside an object:
object My {
object Foo {
val DefaultSize: Int = 10
}
case class Foo(size: Int = Foo.DefaultSize)
}
Now you can use Foo as expected:
scala> new My.Foo()
res0: My.Foo = Foo(10)
scala> new My.Foo(20)
res1: My.Foo = Foo(20)
(I made class Foo a case class to get concise REPL results in the last code block. The answer works without this change, however.)

Can we do conditional imports in Scala?

say I have the following code:
package my
class Foo
class Bar extends Foo
object Chooser {
val isFoo = true
}
I import Foo as:
import my.{Foo => MyClass}
I want to be able to do something like:
If Chooser.isFoo, then:
import my.{Foo => MyClass}
else:
import my.{Bar => MyClass}
I have used Foo in my code as something like this:
object MyObj {
val a = new MyClass
// ...
}
Are there any hidden features of Scala that let me use Bar in place of Foo without modifying the code of MyObj at all. Also what would be the best way to design such code in future so that such extensions are easy?
There isn't but I'm guessing you are more interested in different implementations at runtime than in conditional type import. Your Chooser.isFoo sounds like something that happens during runtime and not in the type system.
One example of how you could do it, since the common type for Foo and Bar is Foo:
val a: Foo =
if (Chooser.isFoo) new my.Foo
else new my.Bar
Edit based on your edit: you could delay the choice by having an abstract type or a type parameter, like so:
class MyObj[T :> Foo] {
val a: T
}
val anInstance = new MyObj[Foo]
val anotherInstance = new MyObj[Bar]
Note the type bound that says that T must be a subclass of Foo, or else you wouldn't know anything about what you can do with a T.
Happen to see this old post & a little curious why it can't do conditional imports in Scala? Maybe old version limit, not sure? But see this, we can import in any place of scala code.
For your scenario, it could be:
try.scala:
package my
class Foo {
}
class Bar extends Foo
object Chooser {
val isFoo = true
}
object MyObj extends App {
if (Chooser.isFoo) {
import my.{Foo => MyClass}
val a = new MyClass
println(a)
} else {
import my.{Bar => MyClass}
val a = new MyClass
println(a)
}
}
run output:
C:\abc\abc>scalac try.scala
C:\abc\abc>scala my.MyObj
my.Foo#6f4a47c7

Scala - construction order and early definition syntax

I'm trying to learn Scala and thought I would begin by reading "Scala for the Impatient". There he cites the problem of construction order by using the following classes:
class Animal {
val range: Int = 10
val env: Array[Int] = new Array[Int](range)
}
class Ant extends Animal {
override val range: Int = 2
}
and then he explained why the env ends up being an empty Array[Int] and proceeds to explain ways to prevent that, including the early definition syntax.
But... can't I prevent that just by doing this:
class Animal(val range: Int = 10) {
val env: Array[Int] = new Array[Int](range)
/* do animal stuff */
}
class Ant(override val range: Int = 2) extends Animal(range) {
/* do ant stuff */
}
??? Why is the early definition syntax really necessary?
I think a better way to look at the need for early instantiation comes from mixing in traits. With traits, you won't have a constructor that you can tweak to get around this kind of issue. Consider this very trivial and completely unrealistic example:
trait Foo{
val bar:String
val barLength = bar.length()
}
object MyFoo extends Foo{
val bar = "test"
}
As it stands right now, this code will throw a NullPointerException when MyFoo is created because bar will not yet be defined when bar.length() is invoked. But if you used early initialization, and redefined MyFoo as:
object MyFoo extends {val bar = "test"} with Foo{
}
then everything works just fine.

Public variables in Scala?

Are there public instance variables anymore in Scala? I'm reading Programming in Scala, which covers Scala 2.8. If I'm understanding it correctly, it claims that vars in 2.8 are by default public.
I'm trying to write code for 2.9.1.final now, and instance variables are now by default private? But there's no public keyword that I'm aware of. (Interestingly enough, it appears it used to exist sometime in the 2.x series, but it mysteriously disappeared somewhere along the line.)
Am I missing something obvious?
Also, by extension, is there an easy way to declare a variable passed to a class constructor to be public (since it appears that those also have default private visibility now too)?
Example:
class Instance(label: String, attributes: Array[Int]){
val f = 0
}
Eclipse claims that label, attributes, and f are all private. Scala 2.9.1.final is being used as the library.
In scala, if you omit the modifer, then instance fields are public by default:
scala> class Foo { var foo = 1 }
defined class Foo
scala> class Bar { def bar() = { val f = new Foo; f.foo = 5; }}
defined class Bar
No worries there. However, when you use a variable in a constructor, the variable is not necessarily turned into a field:
scala> class Foo(foo: Int)
defined class Foo
scala> class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
<console>:8: error: value foo is not a member of Foo
class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
^
so you can declare it as a val or var to have it available:
scala> class Foo(val foo: Int)
defined class Foo
scala> class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
defined class Bar
Note that all fields are actually private, but scala exposes accessor methods (foo() and foo_=(t: Int)) to enable you to access the fields), which is why scala-ide says that the fields are private (assuming you mean when you hover over the variable).

scala: tracing implicits selection and other code magics

When trying to figure how a library works, implicit conversions are confusing. For example, looking at an expression like 'val foo: Foo = 1', what converts 1 to Foo?
Is it possible to instruct the scala library (or REPL) to print out the code paths that are executing while evaluating an expression?
You can add "-Xprint:typer" to the compiler command line (or "-Ybrowse:typer" for a swing GUI browser) to see the code with the conversions explicitly applied.
As an alternative to printing out the conversions, one must realize implicits can't just come out of the blue. You have to bring them into scope in some way. The alternatives are:
Explicit import statement. Watch out for import x.y._ when y is an object, as this is the only way to bring in an implicit into scope.
The object companion of the class that is being converted into something else.
The object companion of the target class, as long as that target is made explicit somehow (such as in your example).
Note that the object scala.Predef is all imported into scope by default, which is how Scala's default implicits get into scope.
scalac -print prints the code after implicit type conversions where applied.
class A{
val x : String = "hi" drop 1
}
Will result in:
package <empty> {
class A extends java.lang.Object with ScalaObject {
#remote def $tag(): Int = scala.ScalaObject$class.$tag(A.this);
private[this] val x: java.lang.String = _;
<stable> <accessor> def x(): java.lang.String = A.this.x;
def this(): A = {
A.super.this();
A.this.x = scala.this.Predef.forceRandomAccessCharSeq(
scala.this.Predef.stringWrapper("hi").drop(1));
()
}
}
}