By chance I came across weird compiling Scala syntax:
class Some extends {
def hi = println("hi")
}
Guys:
Is it an official Scala supported syntax?
Does it mean simply extending the Object?
Does it somehow relate to "duck typing"?
Do you know interesting or tricky usages of this?
Thanks.
This is actually a strange quirk in Scala's syntax. An extraneous extends is allowed before beginning the body of the class. Here are the relevant parts from the Scala Syntax Summary:
ClassDef ::= id [TypeParamClause] {ConstrAnnotation} [AccessModifier]
ClassParamClauses ClassTemplateOpt
ClassTemplateOpt ::= ‘extends’ ClassTemplate | [[‘extends’] TemplateBody]
ClassTemplate ::= [EarlyDefs] ClassParents [TemplateBody]
ClassTemplateOpt is everything after the class's parameters, in this case everything from extends onwards. The usual use of extends is the first alternation of ClassTemplateOpt, with extends being followed either by a parent or an early initializer. However, an early initializer cannot contain a def, and there is no way to interpret the contents of the braces as a parent. It cannot be a structural type because hi has a concrete definition.
The second alternation allows the class parameters to be immediately followed by the class body, without using extends. However, an optional extends is allowed. The extends in OP's code is an example of this, and is exactly equivalent to the same code without the optional extends:
class Some {
def hi = println("hi")
}
This is actually just a syntactical accident (I think). Scala allows early definitions which look like
class Some extends {
...
} with ATrait
so the parser also accepts class Some extends { ... } which is equivalent to class Some { ... } (source).
Yes this is Scala's structural typing or more commonly known as duck typing.
object LoudDuck {
def quack(): String = "QUACK"
}
object QuietDuck {
def quack(): String = "quack"
}
object CowDuck {
def quack(): String = "moo"
}
def quackMyDuck(duck: { def quack(): String }) {
println(duck.quack())
}
scala>quackMyDuck(LoudDuck)
QUACK
scala>
scala>quackMyDuck(QuietDuck)
quack
scala>
scala>quackMyDuck(CowDuck)
moo
You can also declare your stuctural types with the "type" keyword.
type Duck = { def quack(): String }
def quackMyDuck(duck: Duck) {
println(duck.quack())
}
Related
Scala throws "reassignment to val" error for the following code.
abstract case class Gun(var bulletCount:Int)
class Pistol(bulletCount:Int) extends Gun(bulletCount){
def fire() { bulletCount=bulletCount-1 }
}
Anything I missed here?
For starters, you should consider case class as final, and not extend them.
Second, do not use var with case class, you should rather create a copy of a case class to get one of its field changed.
Third, if you want a common type, you can use a base trait.
All in one, here's what it could look like:
sealed trait Gun {
def bulletCount: Int
}
case class Pistol(bulletCount: Int) extends Gun {
def fire(): Pistol = copy(bulletCount=bulletCount)
}
You're referring to bulletCount field generated by Pistol primary constructor parameter. To set base class variable, you need to directly call field using super:
class Pistol(bulletCount: Int) extends Gun(bulletCount) {
def fire(): Unit = {
super.bulletCount = super.bulletCount - 1
}
}
Alternatively, you can label parameter-generated field with override var:
class Pistol(override var bulletCount: Int) extends Gun(bulletCount) {
def fire(): Unit = {
bulletCount = bulletCount - 1
}
}
On a side note, as Frederic A. suggested in his answer, you should avoid inheriting case classes. They are syntactic sugar, and code generation don't work over inheritance - you'll need to implement all the fancy stuff like apply or unapply methods in companion class all by yourself. Scala compiler team tried to support case class to case class inheritance, but discovered that it breaks structural equality and lots of other things.
In the following example, is there a way to avoid that implicit resolution picks the defaultInstance and uses the intInstance instead? More background after the code:
// the following part is an external fixed API
trait TypeCls[A] {
def foo: String
}
object TypeCls {
def foo[A](implicit x: TypeCls[A]) = x.foo
implicit def defaultInstance[A]: TypeCls[A] = new TypeCls[A] {
def foo = "default"
}
implicit val intInstance: TypeCls[Int] = new TypeCls[Int] {
def foo = "integer"
}
}
trait FooM {
type A
def foo: String = implicitly[TypeCls[A]].foo
}
// end of external fixed API
class FooP[A:TypeCls] { // with type params, we can use context bound
def foo: String = implicitly[TypeCls[A]].foo
}
class MyFooP extends FooP[Int]
class MyFooM extends FooM { type A = Int }
object Main extends App {
println(s"With type parameter: ${(new MyFooP).foo}")
println(s"With type member: ${(new MyFooM).foo}")
}
Actual output:
With type parameter: integer
With type member: default
Desired output:
With type parameter: integer
With type member: integer
I am working with a third-party library that uses the above scheme to provide "default" instances for the type class TypeCls. I think the above code is a minimal example that demonstrates my problem.
Users are supposed to mix in the FooM trait and instantiate the abstract type member A. The problem is that due to the defaultInstance the call of (new MyFooM).foo does not resolve the specialized intInstance and instead commits to defaultInstance which is not what I want.
I added an alternative version using type parameters, called FooP (P = Parameter, M = Member) which avoids to resolve the defaultInstance by using a context bound on the type parameter.
Is there an equivalent way to do this with type members?
EDIT: I have an error in my simplification, actually the foo is not a def but a val, so it is not possible to add an implicit parameter. So no of the current answers are applicable.
trait FooM {
type A
val foo: String = implicitly[TypeCls[A]].foo
}
// end of external fixed API
class FooP[A:TypeCls] { // with type params, we can use context bound
val foo: String = implicitly[TypeCls[A]].foo
}
The simplest solution in this specific case is have foo itself require an implicit instance of TypeCls[A].
The only downside is that it will be passed on every call to foo as opposed to just when instantiating
FooM. So you'll have to make sure they are in scope on every call to foo. Though as long as the TypeCls instances are in the companion object, you won't have anything special to do.
trait FooM {
type A
def foo(implicit e: TypeCls[A]): String = e.foo
}
UPDATE: In my above answer I managed to miss the fact that FooM cannot be modified. In addition the latest edit to the question mentions that FooM.foo is actually a val and not a def.
Well the bad news is that the API you're using is simply broken. There is no way FooM.foo wille ever return anything useful (it will always resolve TypeCls[A] to TypeCls.defaultInstance regardless of the actual value of A). The only way out is to override foo in a derived class where the actual value of A is known, in order to be able to use the proper instance of TypeCls. Fortunately, this idea can be combined with your original workaround of using a class with a context bound (FooP in your case):
class FooMEx[T:TypeCls] extends FooM {
type A = T
override val foo: String = implicitly[TypeCls[A]].foo
}
Now instead of having your classes extend FooM directly, have them extend FooMEx:
class MyFoo extends FooMEx[Int]
The only difference between FooMEx and your original FooP class is that FooMEx does extend FooM, so MyFoo is a proper instance of FooM and can thus be used with the fixed API.
Can you copy the code from the third party library. Overriding the method does the trick.
class MyFooM extends FooM { type A = Int
override def foo: String = implicitly[TypeCls[A]].foo}
It is a hack, but I doubt there is anything better.
I do not know why this works the way it does. It must be some order in which the type alias are substituted in the implicitly expression.
Only an expert in the language specification can tell you the exact reason.
By chance I came across weird compiling Scala syntax:
class Some extends {
def hi = println("hi")
}
Guys:
Is it an official Scala supported syntax?
Does it mean simply extending the Object?
Does it somehow relate to "duck typing"?
Do you know interesting or tricky usages of this?
Thanks.
This is actually a strange quirk in Scala's syntax. An extraneous extends is allowed before beginning the body of the class. Here are the relevant parts from the Scala Syntax Summary:
ClassDef ::= id [TypeParamClause] {ConstrAnnotation} [AccessModifier]
ClassParamClauses ClassTemplateOpt
ClassTemplateOpt ::= ‘extends’ ClassTemplate | [[‘extends’] TemplateBody]
ClassTemplate ::= [EarlyDefs] ClassParents [TemplateBody]
ClassTemplateOpt is everything after the class's parameters, in this case everything from extends onwards. The usual use of extends is the first alternation of ClassTemplateOpt, with extends being followed either by a parent or an early initializer. However, an early initializer cannot contain a def, and there is no way to interpret the contents of the braces as a parent. It cannot be a structural type because hi has a concrete definition.
The second alternation allows the class parameters to be immediately followed by the class body, without using extends. However, an optional extends is allowed. The extends in OP's code is an example of this, and is exactly equivalent to the same code without the optional extends:
class Some {
def hi = println("hi")
}
This is actually just a syntactical accident (I think). Scala allows early definitions which look like
class Some extends {
...
} with ATrait
so the parser also accepts class Some extends { ... } which is equivalent to class Some { ... } (source).
Yes this is Scala's structural typing or more commonly known as duck typing.
object LoudDuck {
def quack(): String = "QUACK"
}
object QuietDuck {
def quack(): String = "quack"
}
object CowDuck {
def quack(): String = "moo"
}
def quackMyDuck(duck: { def quack(): String }) {
println(duck.quack())
}
scala>quackMyDuck(LoudDuck)
QUACK
scala>
scala>quackMyDuck(QuietDuck)
quack
scala>
scala>quackMyDuck(CowDuck)
moo
You can also declare your stuctural types with the "type" keyword.
type Duck = { def quack(): String }
def quackMyDuck(duck: Duck) {
println(duck.quack())
}
Consider such code (this is just example not real code):
class Foo(url : String) extends Bar(url)
{
def say() { println(url) }
}
It compiles and it works. With nonsense results "of course". I am too newbie to judge, but for me it serves no purpose but confusion -- by definition it is impossible that the argument of the constructor could be reachable directly in another method.
Could someone more experience in Scala could point out condition when it might work or make sense? Or confirm my suspicion this is flaw in current Scala compiler.
Update
class Bar(val Url : String)
{
}
Why "nonsense". Because my will (no "var" and no "val" in Foo) was to just pass the argument, nothing else. So when I actually use the constructor argument it is just matter of what entity I use by mistake. When you write on purpose, you hit the jackpot each time, but if you don't (i.e. you make a mistake in spelling), you use entities by random. It is not the code does not make sense, it is the computation just does not make sense, I could roll a dice as well. There is a method scope, and I don't see a reason why there shouldn't be constructor scope.
Update -- workaround
So it seems this evil construct is really part of the language (by design). As UserUnknown and Tomasz Nurkiewicz suggested the only line of defense against making stupid typo is convention, however lower-upper case is not good. "A" and "a" differ a lot, but "U" and "u" not much. Introducing one special character (as Tomasz showed) is much better, because it is possible to visually detect fishy usage of constructor argument.
I will use "$" for "just-passing" constructor arguments, it is harder to type for me, and you don't see this character too often in the code.
Thank you for the answers!
Why it is evil? Because implicit actions should be allowed explicitly by users -- good examples are "dynamic" in C#, implicit conversions in Scala. And examples of breaking this rule which led to tons of problems are -- implicit conversions to bool in C++, implicit constructors in C++, declaration by usage in Perl. And this particular case is very, very close to the mentioned perlism, in Perl finally there was change in interpreter to detect such misusages, why Scala repeated the same mistake? I wonder.
Your suspicions are entirely merit-less. This is by design.
Parameters of a class are part of the class. They'll be preserved as field if necessary (such as in your example), or not if they are never used outside construction.
So, basically, if you don't need it as a field, it won't be. If you do, it will. And you'll never write a single extra character of code to tell the compiler what it can figure out by itself.
It's not a bug, it's a feature. In fact, a really nice one. Need an example how useful it is? Here is how I use it with Spring and dependency injection via constructor:
#Service
class Foo #Autowired() (bar: Bar, jdbcOperations: JdbcOperations) {
def serverTime() = bar.format(jdbcOperations.queryForObject("SELECT now()", classOf[Date]))
}
Equivalent code in Java:
#Service
public class Foo
{
private final Bar bar;
private final JdbcOperations jdbcOperations;
#Autowired
public Foo(Bar bar, JdbcOperations jdbcOperations)
{
this.bar = bar;
this.jdbcOperations = jdbcOperations;
}
public String serverTime()
{
return this.bar.format(this.jdbcOperations.queryForObject("SELECT now()", Date.class));
}
}
Still not convinced?
Short tutorial:
class Foo(var x: Int, val y: Int, z: Int) {
println(z)
//def zz = z
}
x will become a variable with getters and setter. y will become an immutable variable and z will become an immutable variable only if zz method is uncommented. Otherwise it will remain a constructor argument. Neat!
UPDATE: I see your point now! The following code works as expected by accessing url variable in base class:
class Bar(val url)
class Foo(_url : String) extends Bar(_url)
{
def say() { println(url) }
}
I agree, this is both ugly and is asking for trouble. In fact I once hit this problem myself when using Scala classes as Hibernate entities - I used constructor parameter instead of field in base class which caused duplicated field to be created: one in base class and one in derived class. I wouldn't even notice but Hibernate was screaming at runtime that duplicated column mapping was defined.
So I have to somewhat agree with you - this is somehow confusing and might be error-prone. This is the price you pay for "implicitness" and concise code.
However note that no modified and val modifier before constructor argument are different. Without modified immutable field is created, while val additionally adds getter.
Scala creates a field from a constructor parameter when such an parameter is referenced by a method in the class. I'm having trouble finding fault with the way that this works.
For the simple case everything works as expected:
scala> class Bar(val url: String)
defined class Bar
scala> class Foo(url: String) extends Bar(url) {
| def say() { println(url) }
| }
defined class Foo
scala> new Foo("urlvalue").say
urlvalue
If we introduce some confusion over the case of the constructor parameter this example still works as expected:
scala> class Bar(val Url: String)
defined class Bar
scala> class Foo(url: String) extends Bar(url) {
| def say() { println(url) }
| }
defined class Foo
scala> new Foo("urlvalue").say
urlvalue
Interestingly you might think that this has worked because it has introduced a lower-case url field in Foo in addition to the upper case Url in Bar, but that doesn't seem to be the case - the compiler seems to be smart enough to know that it can go to Url to get the value of url in say, as no lower case field is generated.
scala> :javap -private Bar
Compiled from "<console>"
public class Bar extends java.lang.Object implements scala.ScalaObject{
private final java.lang.String Url;
public java.lang.String Url();
public Bar(java.lang.String);
}
scala> :javap -private Foo
Compiled from "<console>"
public class Foo extends Bar implements scala.ScalaObject{
public void say();
public Foo(java.lang.String);
}
The only time I can see that this gets confusing is if you mis-spell a var field. In this case you do actually introduce a new field, and the two can get out of step.
scala> class Bar(var Url: String)
defined class Bar
scala> class Foo(url: String) extends Bar(url) {
| def say() { println(url) }
| }
defined class Foo
scala> val f = new Foo("urlvalue")
f: Foo = Foo#64fb7efa
scala> f.say
urlvalue
scala> f.Url = "newvalue"
f.Url: String = newvalue
scala> f.say
urlvalue
scala> :javap -private Foo
Compiled from "<console>"
public class Foo extends Bar implements scala.ScalaObject{
private final java.lang.String url;
public void say();
public Foo(java.lang.String);
}
Assume I want to offer method foo on existing type A outside of my control. As far as I know, the canonical way to do this in Scala is implementing an implicit conversion from A to some type that implements foo. Now I basically see two options.
Define a separate, maybe even hidden class for the purpose:
protected class Fooable(a : A) {
def foo(...) = { ... }
}
implicit def a2fooable(a : A) = new Fooable(a)
Define an anonymous class inline:
implicit def a2fooable(a : A) = new { def foo(...) = { ... } }
Variant 2) is certainly less boilerplate, especially when lots of type parameters happen. On the other hand, I think it should create more overhead since (conceptually) one class per conversion is created, as opposed to one class globally in 1).
Is there a general guideline? Is there no difference, because compiler/VM get rid of the overhead of 2)?
Using a separate class is better for performance, as the alternative uses reflection.
Consider that
new { def foo(...) = { ... } }
is really
new AnyRef { def foo(...) = { ... } }
Now, AnyRef doesn't have a method foo. In Scala, this type is actually AnyRef { def foo(...): ... }, which, if you remove AnyRef, you should recognize as a structural type.
At compile time, this time can be passed back and forth, and everywhere it will be known that the method foo is callable. However, there's no structural type in the JVM, and to add an interface would require a proxy object, which would cause some problems such as breaking referential equality (ie, an object would not be equal with a structural type version of itself).
The way found around that was to use cached reflection calls for structural types.
So, if you want to use the Pimp My Library pattern for any performance-sensitive application, declare a class.
I believe 1 and 2 get compiled to the same bytecode (except for the class name that gets generated in case 2).
If Fooable exists only for you to be able to convert implicitly A to Fooable (and you're never going to directly create and use a Fooable), then I would go with option 2.
However, if you control A (meaning A is not a java library class that you can't subclass) I would consider using a trait instead of implicit conversions to add behaviour to A.
UPDATE:
I have to reconsider my answer. I would use variant 1 of your code, because variant 2 turns out to be using reflection (scala 2.8.1 on Linux).
I compiled these two versions of the same code, decompiled them to java with jd-gui and here are the results:
source code with named class
class NamedClass { def Foo : String = "foo" }
object test {
implicit def StrToFooable(a: String) = new NamedClass
def main(args: Array[String]) { println("bar".Foo) }
}
source code with anonymous class
object test {
implicit def StrToFooable(a: String) = new { def Foo : String = "foo" }
def main(args: Array[String]) { println("bar".Foo) }
}
compiled and decompiled to java with java-gui. The "named" version generates a NamedClass.class that gets decompiled to this java:
public class NamedClass
implements ScalaObject
{
public String Foo()
{
return "foo";
}
}
the anonymous generates a test$$anon$1 class that gets decompiled to the following java
public final class test$$anon$1
{
public String Foo()
{
return "foo";
}
}
so almost identical, except for the anonymous being "final" (they apparently want to make extra sure you won't get out of your way to try and subclass an anonymous class...)
however at the call site I get this java for the "named" version
public void main(String[] args)
{
Predef..MODULE$.println(StrToFooable("bar").Foo());
}
and this for the anonymous
public void main(String[] args) {
Object qual1 = StrToFooable("bar"); Object exceptionResult1 = null;
try {
exceptionResult1 = reflMethod$Method1(qual1.getClass()).invoke(qual1, new Object[0]);
Predef..MODULE$.println((String)exceptionResult1);
return;
} catch (InvocationTargetException localInvocationTargetException) {
throw localInvocationTargetException.getCause();
}
}
I googled a little and found that others have reported the same thing but I haven't found any more insight as to why this is the case.