I have a trait definition:
trait T {
def name: String
}
I can create an object like:
val o = new {
val name: String = "anonymous"
} with T
But I cannot create the object in the following way:
val o = new {
def name: String = "anonymous"
} with T
The compiler said ';' or newline expected in line } with T. The only different is I used def instead of val in the second implementation.
I know that method can be defined in an anonymous object, but why I cannot use in this way here?
The curly brackets in your two examples are "early definitions", explained here:
In Scala, what is an "early initializer"?
So it's initialization code, and not something that gets mixed in to your object.
The idea was raised on the Scala JIRA, and closed as "not a bug", here:
https://issues.scala-lang.org/browse/SI-912
Related
I have a type hierarchy like this:
trait Description {
}
trait DescriptionProvider {
val description: Description
}
object Sample extends DescriptionProvider {
object description extends Description {
val name = "foo"
}
}
Now I am looking for a function f, which gives me the concrete value a.description for any sub type of DescriptionProvider, including it's type.
E.g. f(Sample).name should compile and evaluate to foo.
An obvious accessing method can't work of course
def obvious[T <: DescriptionProvider](x: T) = x.description
obvious(Sample).name // doesn't compile of course, as foo returns only Description.
Is there any Trick how to design such a function f without doing massive changes in the object hierarchy (which is already existent and huge)?
I already tried using a Macro, which somehow works, but IntelliJ doesn't like it (in above Example .name would appear in Red), which makes it pretty hard to use.
I am using Scala 2.10 and can't change right now.
Annotate your return type with a path-dependent one instead of relying on inference:
def obvious[T <: DescriptionProvider](x: T): x.description.type = x.description
I made a Scastie snippet with 2.10.6 and it seems to be working. I cannot check if Intellij would not complain, however.
Why don't you add name to your Description trait:
trait Description {
val name: String
}
trait DescriptionProvider {
val description: Description
}
object Sample extends DescriptionProvider {
object description extends Description {
override val name: String = "foo"
}
}
object Main extends App{
def obvious[T <: DescriptionProvider](x: T) = x.description
val description: String = obvious(Sample).name
println(s"description = ${description}")
}
Now you can compile and run the code. Once you add name to Description trait, compiler knows that a Description has a name.
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())
}
From the ScalaTest docs:
class ExampleSpec extends FlatSpec {
def fixture =
new {
val builder = new StringBuilder("ScalaTest is ")
val buffer = new ListBuffer[String]
}
...
I don't understand how the new keyword is being used here. fixture is obviously a function, which declares and returns... what? It seems to be an object, since it has members (builder & buffer) that can be accessed with . notation.
Is what is being created here an anonymous class that is a subclass of AnyRef?
Yep, it returns instance of anynomous class. It is not hard to check it by yourself in REPL session:
scala> def fixture = new { val string = "mr. String" }
fixture: Object{val string: String}
Java can do the essentially same thing, believe it or not. The following is valid Java
(new Object() {
public void sayHello() {
System.out.println("hello!");
}
}).sayHello();
The Java version is just a mildly more verbose syntax and has a type system limitation that makes it mostly useless.
More about it here http://james-iry.blogspot.com/2009/04/java-has-type-inference-and-refinement.html
Consider the following typical Scala 'pimp' code:
class PimpedA(a:A){
def pimp() = "hi"
}
implicit def pimpA(a:A) = new PimpedA(a)
new A(){
pimp() //<--- does not compile
}
However, changing it to:
new A(){
this.pimp()
}
Makes it work.
Shouldn't it be the same to the Scala compiler?
EDIT : Is there any solution that can make it work without having to add the this.?
Not at all. For it to work, pimp needs to be either an object or an imported member of a value, and it is neither. A class has an "implicit" import this._. It has not a mechanism that auto-prepends this to stuff to see if it compiles.
In this case you should give compiler a hint that pimp() is not a random function. When you write
this.pimp()
compiler know there isn't pimp function on class A so it's an error and before giving up it searches implicit conversion in scope and finds it.
pimpA(this).pimp()
And when you just call pimp() compiler doesn't know what object to pass to the pimpA(a: A) implicit function.
UPDATE
It is hard to understand what is your goal. I can only suggest to make PimpedA a typeclass (Pimp[T] in this example).
trait Pimp[T] {
def action(p: T): String
}
implicit object PimpA extends Pimp[A] {
override def action(p: A) = "some actions related to A"
}
def pimp[T: Pimp](p: T) = implicitly[Pimp[T]].action(p)
class A {
val foo = pimp(this)
}
scala> new A foo
res2: String = some actions related to A
(Essentially I need some kind of a synthesis of these two questions (1, 2), but I'm not smart enough to combine them myself.)
I have a set of JAXB representations in Scala like this:
abstract class Representation {
def marshalToXml(): String = {
val context = JAXBContext.newInstance(this.getClass())
val writer = new StringWriter
context.createMarshaller.marshal(this, writer)
writer.toString()
}
}
class Order extends Representation {
#BeanProperty
var name: String = _
...
}
class Invoice extends Representation { ... }
The problem I have is with my unmarshalling "constructor" methods:
def unmarshalFromJson(marshalledData: String): {{My Representation Subclass}} = {
val mapper = new ObjectMapper()
mapper.getDeserializationConfig().withAnnotationIntrospector(new JaxbAnnotationIntrospector())
mapper.readValue(marshalledData, this.getClass())
}
def unmarshalFromXml(marshalledData: String): {{My Representation Subclass}} = {
val context = JAXBContext.newInstance(this.getClass())
val representation = context.createUnmarshaller().unmarshal(
new StringReader(marshalledData)
).asInstanceOf[{{Type of My Representation Subclass}}]
representation // Return the representation
}
Specifically, I can't figure out how to attach these unmarshalling methods in a typesafe and DRY way to each of my classes, and then to call them from Scala (and hopefully sometimes by using only abstract type information). In other words, I would like to do this:
val newOrder = Order.unmarshalFromJson(someJson)
And more ambitiously:
class Resource[R <: Representation] {
getRepresentation(marshalledData: String): R =
{{R's Singleton}}.unmarshalFromXml(marshalledData)
}
In terms of my particular stumbling blocks:
I can't figure out whether I should define my unmarshalFrom*() constructors once in the Representation class, or in a singleton Representation object - if the latter, I don't see how I can automatically inherit that down through the class hierarchy of Order, Invoice etc.
I can't get this.type (as per this answer) to work as a way of self-typing unmarshalFromJson() - I get a compile error type mismatch; found: ?0 where type ?0 required: Representation.this.type on the readValue() call
I can't figure out how to use the implicit Default[A] pattern (as per this answer) to work down my Representation class hierarchy to call the singleton unmarshalling constructors using type information only
I know this is a bit of a mammoth question touching on various different (but related) issues - any help gratefully received!
Alex
The key is to not try and attach the method to the class but rather pass it in as a parameter. To indicate the type you are expecting and let the type system handle passing it in. I tried to make the unmarshal invocation something that reads a little DSL like.
val order = UnMarshalXml( xml ).toRepresentation[Order]
The following is a fully testable code snippet
abstract class Representation {
def marshalToXml(): String = {
val context = JAXBContext.newInstance(this.getClass)
val writer = new StringWriter
context.createMarshaller.marshal(this, writer)
writer.toString
}
}
#XmlRootElement
class Order extends Representation {
#BeanProperty
var name: String = _
}
case class UnMarshalXml( xml: String ) {
def toRepresentation[T <: Representation](implicit m:Manifest[T]): T = {
JAXBContext.newInstance(m.erasure).createUnmarshaller().unmarshal(
new StringReader(xml)
).asInstanceOf[T]
}
}
object test {
def main( args: Array[String] ) {
val order = new Order
order.name = "my order"
val xml = order.marshalToXml()
println("marshalled: " + xml )
val received = UnMarshalXml( xml ).toRepresentation[Order]
println("received order named: " + received.getName )
}
}
You should see the following output if you run test.main
marshalled: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><order><name>my order</name></order>
received name: my order
Here's the updated version of Neil's code which I used to support the second use case as well as the first:
case class UnmarshalXml(xml: String) {
def toRepresentation[T <: Representation](implicit m: Manifest[T]): T =
toRepresentation[T](m.erasure.asInstanceOf[Class[T]])
def toRepresentation[T <: Representation](typeT: Class[T]): T =
JAXBContext.newInstance(typeT).createUnmarshaller().unmarshal(
new StringReader(xml)
).asInstanceOf[T]
}
This supports simple examples like so:
val order = UnmarshalXml(xml).toRepresentation[Order]
But also for abstract type based usage, you can use like this:
val order = UnmarshalXml(xml).toRepresentation[T](typeOfT)
(Where you have grabbed and stored typeOfT using another implicit Manifest at the point of declaring T.)